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);
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>
usingnamespace 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);
}
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>
usingnamespace 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.
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.
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.
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.