88

This:

const char * terry = "hello";
cout<<terry;

prints hello instead of the memory address of the 'h'. Why is this happening?

Garrett
  • 4,007
  • 2
  • 41
  • 59
Mr.Puff
  • 899
  • 1
  • 7
  • 4
  • Does this answer your question? [Why does cout print char arrays differently from other arrays?](https://stackoverflow.com/questions/501816/why-does-cout-print-char-arrays-differently-from-other-arrays) – Melebius Jul 20 '20 at 06:39

6 Answers6

106

The reason for that is that std::cout will treat a char * as a pointer to (the first character of) a C-style string and print it as such. If you want the address instead, you can just cast it to a pointer that isn't treated that way, something like:

cout << (void *) terry;

(or use the const void * cast if you're worried about casting away constness, something that's not an issue in this particular case).


If you're more of a purist than pragmatist, you can also use the C++ static_cast, along the lines of:

cout << static_cast <const void *> (terry);

though it's unnecessary in this particular case, the cast to a void * will work fine. The following sample code shows all these options in action:

#include <iostream>
int main (void) {
    const char *terry = "hello";
    std::cout << terry << '\n';
    std::cout << (void *) terry << '\n';
    std::cout << (const void *) terry << '\n';
    std::cout << static_cast<const void *> (terry) << '\n';
    return 0;
}

outputting (the address may be different in your environment):

hello
0x8048870
0x8048870
0x8048870

Note that, when using the static_cast, you should ensure you don't try to cast away the constness with static_cast <void *> (that's what const_cast is for). This is one of the checks done by the newer C++ casts and the old-style cast does not have this limitation.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 2
    It doesn't treat the `char*` value as a C-style string; it treats it as a *pointer* to (the first character of) a C-style string. – Keith Thompson Jul 23 '13 at 14:47
  • 1
    @Keith, semantics problem, apologies for that. What I meant is that it prints it out as a C-style string. I'll clarify. – paxdiablo Jul 23 '13 at 14:48
  • Is the word "semantics" meant to imply that it's an unimportant distinction? It isn't. – Keith Thompson Jul 23 '13 at 14:51
  • 1
    @Keith, no, it wasn't meant to mean unimportant (otherwise I wouldn't have changed it). I meant I didn't get my meaning across as well as I should have. Hopefully, the edits have fixed that. – paxdiablo Jul 23 '13 at 14:53
  • 1
    Please don't use C-style cast. Dangerous, unclear, hard to spot. (For example, here you dropped constness without thinking of it.) – gx_ Jul 23 '13 at 14:54
  • 4
    It's only dangerous to those who don't know what they're doing. Dropping of constness is irrelevant in this case since you're not doing anything with the pointer where that will matter. Yes, if you'd cast the pointer then gone off and used it incorrectly, I'd agree, but I expect practitioners of a language to learn hozw to use it safely. I didn't let my son start using my more dangerous tools until he'd proven he knew the issues with them :-) – paxdiablo Jul 23 '13 at 15:04
  • 4
    I see only 2 reasons of using a C-style cast in C++: 1. cast to an inaccessible base class; 2. laziness to type a few more characters. – gx_ Jul 23 '13 at 15:15
  • 9
    You talk of laziness as if it's a _bad_ thing. It's only bad if there's an actual decremental effect, otherwise it's known as efficiency. There are no problems with using old-style casts in _this particular_ situation and they're as much a part of the C++ language as any other (even stuff like cstdio is acceptable provided you understand the issues). – paxdiablo Jul 23 '13 at 22:09
  • 2
    However, I can see I'm unlikely to convince you. The battle between purist and pragmatist seems to be rearing its head here, both sides have their points but we may as well be discussing vi vs. emacs :-) So I suggest you vote your conscience and we'll let the people decide. I'll add the newer style as an option but I still maintain it's not necessary in this case. – paxdiablo Jul 24 '13 at 02:31
  • If pointer points to a single character variable, what should be the output of cout? In the below case, I get some C followied by 3 garbage characters: char a='C'; char *ptr3=&a; cout<<"ptr = "< – Rajesh Sep 03 '17 at 13:05
  • @Rajesh, what is *should* be could be a matter for discussion :-) What it will most likely be is basically the character followed by random output, depending on whatever arbitrary data comes *after* that character in memory. By using a `char*`, you are declaring that there is a C-style string at that location. If there actually *isn't,* then all bets are off. – paxdiablo Sep 03 '17 at 14:23
  • @paxdiablo Can you provide a reference to any other SO post which talks about `constness` in detail? I am pretty new to `C++`. – asn Jan 13 '19 at 05:10
29

The << operator on std::cout is overloaded. Its behavior depends on the type of the right operand. (It's actually several different functions, all named operator<<; the compiler decides which one to call.)

If you give it a char* or const char*, it treats the operand as a pointer to (the first character of) a C-style string, and prints the contents of that string:

const char * terry = "hello";
cout << terry; // prints "hello"

If you give it a char value, it prints that value as a character:

cout << *terry;   // prints "h"
cout << terry[0]; // the same

If you give it a pointer of type void*, it prints that pointer value (in some implementation-defined way, typically hexadecimal):

cout << static_cast<const void*>(terry); // prints something like 0x4008e4

Treating a char* or const char* as a pointer to a C-style string is a special case, and the only one (that I can think of) that causes operator<< to print something other than the value of the operand. The reason for this goes back to C++'s roots in C, which doesn't have a "string" type and manipulates strings via char* pointers.

There are numerous other overloads for operator<<, for various integer and floating-point numeric types, for std::string, and so forth.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Another "special" case I can think of is trying to print a function pointer, which will choose the `bool` overload (unless the function has the signature of a stream manipulator): http://ideone.com/OkutRD (admittedly, it prints the "value" of the pointer converted to `bool`, so this is "less special" than the `const char*` case) – gx_ Jul 23 '13 at 16:31
  • @KeithThompson So, that means that it's the `overloaded version` of `operator<<` that makes the string get printed and not the pointer value while in case of something like `int*` the pointer value will get printed and not the value. Am I correct here? – asn Jan 13 '19 at 05:08
13

You should change your code to this:

cout << static_cast<const void*>(terry);

The problem is that << operator is overloaded for pointers to C-style strings for printing the content of the string. If you cast it to the raw pointer instead, you will have the default behaviour of printing pointer using iostreams as you want.

sasha.sochka
  • 14,395
  • 10
  • 44
  • 68
5

std::cout is defined as std::ostream with this definition of operator<<.

Notably this line:

template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os,
                                     const char* s );

This gets selected when you use << with an argument of type char*.

The case of any other non-char pointer type goes here:

basic_ostream& operator<<( const void* value );

This continues to std::num_put which is made for formatting numeric values. Therefore, the pointer is interepreted numerically like %p in C formatting functions.

IS4
  • 11,945
  • 2
  • 47
  • 86
2

cout is overloaded so that when you give it a char*, it will print as a pointer to a C-style string. So, it prints out the characters until it hits a null terminating character.

If you used printf instead of cout, you would see the address. You could also cast the pointer to another type, say (void*) and you would also get the address.

CoffeeTableEspresso
  • 2,614
  • 1
  • 12
  • 30
Richard Fung
  • 1,020
  • 6
  • 14
  • 3
    `printf` itself doesn't decide how it prints, you still have to use the correct format specifier, the same way you have to use the same type in C++. For example, `printf` with `%s` will have exactly the same issue as `cout` with a `char *`. To get the pointer, you'd use a format specifier `%p`. – paxdiablo Jul 04 '15 at 04:52
-2

"hello" is a string, i.e. the char array. const char* is a pointer to this array, so when you dereference this pointer, you get the value of the first element.

It is like if you have

int a[] = {1, 2, 3};
int *b = a;
cout << *b << endl;

you get just 1 printed.

Ivan Smirnov
  • 4,365
  • 19
  • 30
  • why im not getting the memory address? – Mr.Puff Jul 23 '13 at 14:45
  • 1
    @Mr.Puff If you want to get the memory address of char pointer, you should cast it to void pointer before, because `ostream <<` operator is overloaded for char pointers to print strings. – Ivan Smirnov Jul 23 '13 at 14:48