开发者

Why does the inclusion of an unused bool affect the reference of a char?

This code...

#include <iostream>

int main(int argc, char * argv[])
{
    char c = 'A';
    std::cout << &c;
    return 0;
}

...correctly outputs "A" both in Eclipse debug mode and on the command line.

H开发者_运维问答owever when I modify the code to...

#include <iostream>

int main(int argc, char * argv[])
{
    char c = 'A';
    bool b = true;
    std::cout << &c;
    return 0;
}

...it outputs "A␁" (the latin letter 'A' followed by the 'start of header' ASCII control character) in Eclipse debug mode and on the Windows 7 command line. Incidentally, when using bool b = false instead I don't get the ␁ character.

I know ␀ has the value 0, and ␁ has the value 1, but why is cout << &c affected by the bool? Can anyone explain why this is?

Edit: forgot to add my environment: Windows 7 64-bit, MinGW with g++ 4.5.2, in Eclipse Indigo


In the first version you are getting (un)lucky.

In the second one you are getting (un)lucky (that it does not crash) but it prints more garbage.

When you use & on a char object you get a char*. When you try and stream a char* it acts differently to all other pointers (which normally prints the address). But a char* is assumed to be a C-String. A C-String is a sequence of bytes terminated by a null character '\0';

What is actually happening is that it is printing every memory location (treating it as a char) starting at the variable 'c' and moving through memory until it finds the character '\0'

Example 1 above:

In your case you are lucky there happens to be a null character lying around in memory just after the variable 'c'.

Example 2 above:

In your case you are lucky there happens to be a null character lying around in memory just after the variable 'b'. But the variable 'b' is also be interpreted.

  • When the value of 'b' is false: converted to a char this is '\0' (same thing). So only the letter 'A' is printed.
  • When the value of 'b' is true: converted to a char this is '\01'. Not '\0' so it is printed. You are then lucky that the next byte is a '\0' and the printing stops.

What you actually wanted to do was:

std::cout << c; // prints a character

Or you could have created a string:

char const* c = "A";  // Creates a null terminated C-String. Note the double quotes " "

Or to get the address

std::cout << static_cast<void*>(&c); // All other pointer types will print the address
                                     // Of the standard types only char* is treated 
                                     // differently with its own overload.


&c is not passing a reference to c, it is passing the address of c. That is, you're passing a char* to operator<<. The function will walk memory starting with &c and ending when it finds a \0.

Because you don't have a null-terminated string, you're invoking undefined behavior as the function walks past the end of c's memory.

Have you tried the following?

#include <iostream>

int main(int argc, char * argv[])
{
    char c = 'A';
    std::cout << c << std::endl; // no & needed.
    return 0;
}


A char* is assumed to point to a C style string (zero terminated), not a single character.

If you want to display the address (pointer value) instead, try

cout << static_cast<void*>(&c);


Short answer: operator<< is passed the address of a char, and assumes that it is the address of the first char in a nullterminated string. It isn't, except by happenchance. The code has UB.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜