被(字符*)演员表所迷惑

Confused by (char *) cast

本文关键字:迷惑 字符      更新时间:2023-10-16
struct myStruct
{
  int foo;
}
myStruct bar;
bar.foo = 123;
cout<<(char *) &bar<<endl;

cout 语句打印出"{"。123 的 ASCII 实际上是 '{' (bar.foo = 123.更改此值会打印出不同的字符(。我不明白的是

cout<<(char *) &bar<<endl;

应该在技术上打印酒吧的地址。如何使用 (char *( 强制转换访问结构内的数据?使用 (int *( 仍返回地址。我确实知道 (char *( 会导致数据以逐字节的方式排列,但这不应该只影响地址吗?

<< 有一个重载 const char * ,它将操作数解释为指向 C 样式的零终止字符串的指针。例如,这就是使用的重载

cout << "Hellon";

如果像这里一样,你给它一个指向 C 样式字符串以外的内容的指针,你将得到未定义的行为。在实践中,它将逐字节打印内存的内容,直到达到零值字节或离开可读内存的末尾。

char*上的<<将其视为 C 字符串,而不是指针。此程序将myStruct解释为 sizeof(myStruct) 字节的缓冲区,并依靠字节序来确保它以 NUL 终止。

要打印地址,只需传递&bar,无需强制转换。

由于bar是myStruct结构的对象,因此其起始地址和myStruct中第一个成员的起始地址(即bar.foo(将是相同的。所以 &bar 会给你 bar 对象的起始地址,char* 会给你提供该地址位置的第一个字节的值。

int * 不同,char *是特殊类型的指针,它们也用于指向 ASCII 字符串,如下所示:

const char * s = "hello world";

对于表达式(char *) &bar结果是一个char *指针,因此cout将打印一个字符串,因为它有一个特殊的运算符,用于输出字符串的char *。 对于int *没有运算符,只有一个只打印地址的指针的泛型运算符。

std::ostream通常对operator <<具有char *绑定到的const char *的重载。

此重载将其参数视为以 null 结尾的 ASCII 字符字符串。

如果需要输出 myStruct 的内容到输出流,则需要为您的结构定义 ostream <<运算符,如下所示:

std::ostream& operator <<(std::ostream& os, const myStruct& ms) 
{
    os << "myStruct { foo: " << ms.foo << "n}";
    return os; 
}

(字符 *( 不会重新排列任何内容。该结构在内存中存储为 4 字节 = sizeof(int( 或 64 位 CPU 上的 8 字节,具体取决于小端或大端布局中的处理器架构(请参阅 http://en.wikipedia.org/wiki/Endianness(。

您的代码可能在 x86 体系结构 CPU 上运行,因此最低有效字节存储在较低的地址。例如,foo中的数字123将存储为字节7B 00 00 00。在记忆中。您的 cast co char * 将告诉编译器对 char * 数组使用 ostream 运算符,该数组在 C 中用作字符串。 每个字节被解释为一个字符,以 0 字节结尾。字节 123 对应于 ASCII 字符"{",它以字节 00 终止,因此在这种情况下您的代码不会崩溃。其他值可能会使代码崩溃,或者在超出结构存储范围的堆栈上打印字节(直到遇到零字节或崩溃(。

希望这有帮助。

实际上,您的代码正在打印结构变量栏的地址而不是foo的值。char*(&bar 正在将结构类型的地址转换为 (char*( 表示 C 字符串类型。一些 c,c++ 函数参数确实将结构类型作为参数,因此我们需要根据函数参数将结构类型转换为 (char*( 或 (void*(。