为什么包含未使用的 bool 会影响 char 的引用?

发布于 2024-11-28 23:26:36 字数 792 浏览 3 评论 0原文

此代码...

#include <iostream>

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

...在 Eclipse 调试模式和命令行中都正确输出“A”。

然而,当我将代码修改为...

#include <iostream>

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

...它在 Eclipse 调试模式和 Windows 7 命令行上输出“A␁”(拉丁字母“A”后跟“标头开始”ASCII 控制字符)。顺便说一句,当使用 bool b = false 代替时,我没有得到 ␁ 字符。

我知道 ␀ 的值为 0,␁ 的值为 1,但是为什么 cout << &c 受 bool 影响吗?谁能解释这是为什么吗?

编辑:忘记添加我的环境:Windows 7 64位,MinGW with g++ 4.5.2,在Eclipse Indigo中

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.

However 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蓝天 2024-12-05 23:26:36

在第一个版本中,你很幸运。

在第二个中,你很幸运(它没有崩溃),但它打印了更多垃圾。

当您使用 &在 char 对象上你会得到一个 char*。当您尝试流式传输 char* 时,它的行为与所有其他指针(通常打印地址)不同。但 char* 被假定为 C 字符串。 C 字符串是一个以空字符“\0”结尾的字节序列;

实际发生的情况是,它打印从变量“c”开始的每个内存位置(将其视为字符)并在内存中移动,直到找到字符“\0”

上面的示例 1:

在您的情况下,您很幸运恰好是内存中变量“c”之后的空字符。

上面的示例 2:

在您的情况下,您很幸运,内存中恰好在变量“b”之后有一个空字符。但变量“b”也可以被解释。

  • 当“b”的值为 false 时:转换为字符,这是“\0”(相同)。所以只打印字母“A”。
  • 当“b”的值为 true 时:转换为字符即为“\01”。不是 '\0',因此被打印。幸运的是,下一个字节是“\0”并且打印停止。

你真正想做的是:

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

或者你可以创建一个字符串:

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

或者获取地址

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.

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.
雨后彩虹 2024-12-05 23:26:36

&c 不是传递对 c 的引用,而是传递 c 的地址。也就是说,您将 char* 传递给 operator<<。该函数将从 &c 开始遍历内存,并在找到 \0 时结束。

因为您没有以 null 结尾的字符串,所以当函数经过 c 内存末尾时,您将调用未定义的行为。

您尝试过以下方法吗?

#include <iostream>

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

&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;
}
街道布景 2024-12-05 23:26:36

假定 char* 指向 C 样式字符串(以零结尾),而不是单个字符。

如果您想显示地址(指针值),请尝试

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

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);
岁月染过的梦 2024-12-05 23:26:36

简短回答operator<< 传递char 的地址,并假设它是第一个char 的地址 在以 null 结尾的字符串中。事实并非如此,除非是偶然。代码中有UB。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文