Simple Question--char *

1 view
Skip to first unread message

dave

unread,
Feb 7, 2006, 6:20:51 AM2/7/06
to
I think I understand that

char * ptr = "string"

declares a pointer initialized to a possibly modifiable constant string.

So, I thought I knew what I would see when I ran the following:

char * char_ptr = "stringthingy";
int integer = 1234;
int * int_ptr = &integer;
...
cout << "Size of char_ptr is " << sizeof(char_ptr) << "\n\n";
cout << "*char_ptr = " << *char_ptr << "\n";
cout << "char_ptr = " << char_ptr << "\n";

cout << "Size of int_ptr is " << sizeof(int_ptr) << "\n\n";
cout << "*int_ptr = " << *int_ptr << "\n";
cout << "int_ptr = " << int_ptr << "\n";

But, I was surprised to see this result:

Size of char_ptr is 4
*char_ptr = s
char_ptr = stringthingy

Size of int_ptr is 4
*int_ptr = 1234
int_ptr = 0x804e03c

Why is the non-deferenced char_ptr not an address in memory?? The
non-dereferenced int_ptr result is. Is "<<" overloaded to dereference
a char ptr? If so, why not for an int ptr? If it is overloaded, why
does "<< char_ptr" produce a different result from "<< *char_ptr"?

I am a bit confused.


TIA,

~Dave~


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Kurt Stege

unread,
Feb 7, 2006, 9:15:49 AM2/7/06
to
dave wrote:
> I think I understand ...

I think you understand quite much about pointers and C++.
Examples and details to questions snipped...

> Is "<<" overloaded to dereference a char ptr?

Yes. In a way that the pointer is interpreted as an
old fashioned pointer to a zero terminated string.
The reason is to allow things like

std::cout << "Hello World!\n";

In this context you expect to see the string, and
not the address of the string as output.

> If so, why not for an int ptr?

The reason for char ptr does not work for int ptr.

> If it is overloaded, why
> does "<< char_ptr" produce a different result from "<< *char_ptr"?

Because << is overloaded, not *. *char_ptr is of type char.
And << called with a char outputs exactly that one character,
as expected by std::cout << '\n';

It would be possible to overload << to take the address of the
given char and output the following characters in memory as well,
but this is far from useful and nobody has done it.

> I am a bit confused.

That is good. A sign for real understanding.

Best regards,
Kurt.

Valentin Samko

unread,
Feb 8, 2006, 4:54:39 AM2/8/06
to
dave wrote:
> char * ptr = "string"
> declares a pointer initialized to a possibly modifiable constant string.
It's not modifiable. ptr is modifiable, the string it points to - no.

> So, I thought I knew what I would see when I ran the following:
> char * char_ptr = "stringthingy";
> int integer = 1234;
> int * int_ptr = &integer;

> cout << "*int_ptr = " << *int_ptr << "\n";

And here you get an undefined behaviour, as you are dereferencing an int ptr which points
to a storage area which was not initialised as an integer.

> Why is the non-deferenced char_ptr not an address in memory?? The
> non-dereferenced int_ptr result is. Is "<<" overloaded to dereference
> a char ptr?

Yes

> If so, why not for an int ptr?

How would you expect it to work for int ptr?

> If it is overloaded, why
> does "<< char_ptr" produce a different result from "<< *char_ptr"?

Because in addition to be consistent (char* and char are different types, first points to
possibly more than one character, and the second one is always one character), this is
required by the standard, see 27.6.2.5.4/4

--

Valentin Samko - http://www.valentinsamko.com

Alberto Ganesh Barbati

unread,
Feb 8, 2006, 8:25:17 AM2/8/06
to
dave ha scritto:

> I think I understand that
>
> char * ptr = "string"
>
> declares a pointer initialized to a possibly modifiable constant string.

Your understanding is not entirely correct. 2.13.4/2 says that "The
effect of attempting to modify a string literal is undefined." So, if
you modify the string, you do it at your own risk: the application may
run without errors or ignore the modifications or crash or even format
your hard-disk.

In fact the type of a string literal is "array of n const char" (notice
the const). The quirk is that a string literal can be used to initialize
a char*. This is an exception whose use is deprecated and that is kept
mainly for backward compatibility with C and older C++ programs.

> Why is the non-deferenced char_ptr not an address in memory?? The
> non-dereferenced int_ptr result is. Is "<<" overloaded to dereference
> a char ptr? If so, why not for an int ptr? If it is overloaded, why
> does "<< char_ptr" produce a different result from "<< *char_ptr"?

Don't confuse "to be an address in memory" with "to be output on cout as
something that resembles an address in memory"! operator<< simply
provides a textual representation of the right operand, but what the
"textual representation" is can differ according to the type of the
argument.

As you already realized, operator<< has several overloads to provide
textual representation of integers, floats, etc. and among them there
are overloads for const char* and for const void*. A const char* is
assumed to be pointing to a null-terminated character string, so its
textual representation is the characters in the string itself. Compare
with the typical statement

std::cout << "hello, world\n";

That explains why your char* is output as a string and not as an address.

With const void* you can't assume that it points to anything meaningful,
so the operator<< behaves as the printf "%p" format specifier which
outputs an implementation-defined representation of the pointer
(typically, its address in numeric form).

For pointer types different from const char* (including signed and
unsigned variations) the compiler always choses the overload for const
void* and that's why your int* is output as an address.

HTH,

Ganesh

kanze

unread,
Feb 8, 2006, 9:01:40 AM2/8/06
to
dave wrote:
> I think I understand that

> char * ptr = "string"

> declares a pointer initialized to a possibly modifiable
> constant string.

Not quite. The string is not "possibly modifiable"; it's not
modifiable at all. The lack of const in the type is a lie,
supported for reasons of backward compatibility only; you really
should write this:

char const* ptr = "string" ;

> So, I thought I knew what I would see when I ran the following:

> char * char_ptr = "stringthingy";
> int integer = 1234;
> int * int_ptr = &integer;
> ...
> cout << "Size of char_ptr is " << sizeof(char_ptr) << "\n\n";
> cout << "*char_ptr = " << *char_ptr << "\n";
> cout << "char_ptr = " << char_ptr << "\n";
>
> cout << "Size of int_ptr is " << sizeof(int_ptr) << "\n\n";
> cout << "*int_ptr = " << *int_ptr << "\n";
> cout << "int_ptr = " << int_ptr << "\n";

> But, I was surprised to see this result:

> Size of char_ptr is 4
> *char_ptr = s
> char_ptr = stringthingy

> Size of int_ptr is 4
> *int_ptr = 1234
> int_ptr = 0x804e03c

> Why is the non-deferenced char_ptr not an address in memory??
> The non-dereferenced int_ptr result is. Is "<<" overloaded to
> dereference a char ptr?

Exactly. (For char const*, actually, but the conversion to char
const* is better than the convertion to void const*.)

> If so, why not for an int ptr?

Because the overload for char const* was necessary to support
string literals. You cannot define a function to take a char
const[] (the actual type of a string literal) as a parameter;
the closest you can come is a function which accepts char
const*.

> If it is overloaded, why
> does "<< char_ptr" produce a different result from "<< *char_ptr"?

Because the overload of << for char (the result type of
*char_tpr) outputs a single char -- which is all it can do, if
we also allow "<< '\n'" and such things. The overload of char
const*, on the other hand, interprets the address as the start
of a '\0' terminated string.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Francis Glassborow

unread,
Feb 8, 2006, 11:39:16 AM2/8/06
to
In article <gO9Gf.83683$eD5.1...@twister2.libero.it>, Alberto Ganesh
Barbati <Alberto...@libero.it> writes

>For pointer types different from const char* (including signed and
>unsigned variations) the compiler always choses the overload for const
>void* and that's why your int* is output as an address.

I suspect not. What if I provide an overload for operator << that takes
a mytype* as an argument:

ostream & operator << (ostream &, mytype * const &);

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Kurt Stege

unread,
Feb 8, 2006, 2:19:13 PM2/8/06
to
Valentin Samko wrote:
> dave wrote:
>
>> char * ptr = "string"
>>declares a pointer initialized to a possibly modifiable constant string.
>
> It's not modifiable. ptr is modifiable, the string it points to - no.

Yes. Here you are more or less right. It is allowed to write the
code *ptr='x'; but when executing that line it results in undefined
behaviour.

I suppose, dave noticed this curious behaviour of C++ and thus
called id "possibly modifiable", as "you can but you can't".


>>So, I thought I knew what I would see when I ran the following:
>> char * char_ptr = "stringthingy";
>> int integer = 1234;
>> int * int_ptr = &integer;
>> cout << "*int_ptr = " << *int_ptr << "\n";
>
> And here you get an undefined behaviour, as you are dereferencing an int ptr which points
> to a storage area which was not initialised as an integer.

You have noticed the line int_ptr = &integer?

Best regards,
Kurt.

Valentin Samko

unread,
Feb 9, 2006, 4:53:00 AM2/9/06
to
Kurt Stege wrote:
>>> char * ptr = "string"
> Yes. Here you are more or less right. It is allowed to write the
> code *ptr='x'; but when executing that line it results in undefined
> behaviour.
I wouldn't say that something is "doable" in a language if this results in an undefined
behaviour. Otherwise one could say that dereferencing a 0 pointer is allowed in C++.

>> And here you get an undefined behaviour, as you are dereferencing an int ptr which points
>> to a storage area which was not initialised as an integer.
> You have noticed the line int_ptr = &integer?

No I haven't :) There is no undefined behaviour there.

--

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Alberto Ganesh Barbati

unread,
Feb 9, 2006, 5:09:28 AM2/9/06
to
Francis Glassborow ha scritto:

> In article <gO9Gf.83683$eD5.1...@twister2.libero.it>, Alberto Ganesh
> Barbati <Alberto...@libero.it> writes
>> For pointer types different from const char* (including signed and
>> unsigned variations) the compiler always choses the overload for const
>> void* and that's why your int* is output as an address.
>
> I suspect not. What if I provide an overload for operator << that takes
> a mytype* as an argument:
>
> ostream & operator << (ostream &, mytype * const &);
>

Sure, I should have said "always choses the overload for const void*
unless you provide additional overloads". Thanks for pointing that out.

Ganesh

Reply all
Reply to author
Forward
0 new messages