cout doesn't output the same as printf, why?

First I define a single character 'b' as variable b. Then I try to print the address using both cout and printf, but cout spits out a bunch of garbage while printf spits out the address. Why is this?

1
2
3
4
5
6
7
8
 	bool a = true;
	char b = 'b';
	int c = 5;
	float d = 5.5;
	double e = 5.75;

	cout << &b << endl;
	printf("char b stores letter %c at the location %d in the memory \n", b, &b);


Thanks in advance!
std::cout needs to know what overloaded << to use. Taking the address as you call << doesn't make it treat the value as an address. To do so try casting it std::cout << (void*)&b;. This will print out it's address by telling very clearly you're giving a pointer.

P.S. Isn't %p for pointer values? Why do you use %d?
It prints out garbage because you're invoking undefined behavior on line 7.
When you call operator<<(ostream&, char*);, it treats the char* like a null-terminated c-string. (It treats it like how printf would treat %s.) This is not what you want.

You should enable warnings (-Wall), I get the same warning as Too Explosive.

And just to nicely make it compilable for others:
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
int main()
{
	char b = 'b';
	cout << (void*)&b << endl;
	printf("char b stores letter %c at the location %p in the memory \n", b, &b);
}
Last edited on
So basically operator<<(ostream&, char*); has some weird quirk when it comes to single characters where it looks for a '\0' character, never finds it, and outputs junk? Why doesn't it do this for strings with multiple characters? Is it because when you define a string with multiple characters using char it automatically includes the '\0'?

1
2
3
4
5
6
#include <iostream>
using namespace std;
int main()
{
	char b = "bee";
	cout << &b << endl;
char b = "bee";
That should not compile with any reasonable compiler. (I usually use g++)

In function 'int main()':
7:14: error: invalid conversion from 'const char*' to 'char' [-fpermissive]


You can call it a "weird quirk" but it's pretty intuitive to me. It's just as weird as having a function that expects a const char* string, and the user passes in a char pointer that points to a single char (which therefore isn't null-terminated). This is an ambiguity that carried over from C. C has the same problem.

Edit: To clarify, you're doing the same thing as trying to say %s when you pass in a char pointer that points to a single char. That would be undefined behavior in C, too.

Edit 2: This is what allows constructs like
std::cout << "Hello, world!\n"; to be possible. It interprets the const char* as a null-terminated c-style string.
Last edited on
The bad thing about printf is that you need to tell it the types of the things you are printing. It's easy to get that wrong, like you did in your example, using %d instead of the correct %p. A decent compiler with a reasonable warning level would have issued a warning about that.

cout has been defined with various overloads to handle the different types (and you can define your own overloads for your own types) and C++ picks the correct one depending on the type you pass it. A char* is overloaded to print a c-style (zero-terminated) string, and such a string is assumed to be properly formed and thus have a zero byte somewhere within its allocated memory. To print a pointer value you need to cast it as void* as has been said.

When you say

 
char b[] = "bee";

it's basically shorthand for

 
char b[4] = {'b', 'e', 'e', '\0'};

Last edited on
So basically operator<<(ostream&, char*); has some weird quirk when it comes to single characters where it looks for a '\0' character, never finds it, and outputs junk?


operator<<(ostream&, char*) treats a char* as if it was a C-style string. That's not a "weird quirk", that's highly useful behaviour that's beneficial for the overwhelming majority of cases where you want to send a char* to a stream.

It would be much less useful if the default behaviour were to simply display the address stored in the pointer.

Last edited on
Well, it's highly inconsistent, but I think most people think it's worth it. How often do you print memory addresses anyway?
Well, it's highly inconsistent

It's useful, and 99.99% of the time is what you want. I'll take that over mere consistency any day.
It's by no means perfect, but I'm honestly not sure what "inconsistent" means here. Many classic C functions expect null-terminated char pointers, and will fail if just given a pointer to a single char. operator<<(ostream, char*) masks this due to operator overloading (not directly specifying %s), but the behavior is still the same.

It's really just a fundamental ambiguity in the C language that then got carried over to C++ through necessity, sadly.
Last edited on
I'm honestly not sure what "inconsistent" means here

The inconsistency is that cout<<ptr; sometimes prints the pointer address and sometimes prints the data that the pointer points to.

printf("%p", ptr); is consistent and treats all pointer types the same.
operator<<(ostream&, char*) would have been highly inconsistent and illogical, if it did exist.
The standard library tends to be const-correct.
operator<<(ostream&, char*) would have been highly inconsistent and illogical, if it did exist.
The standard library tends to be const-correct.

Good catch!
Topic archived. No new replies allowed.