被(char *)演员混淆

时间:2013-11-19 10:18:25

标签: c++ casting ampersand

struct myStruct
{
  int foo;
}

myStruct bar;
bar.foo = 123;
cout<<(char *) &bar<<endl;

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

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

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

7 个答案:

答案 0 :(得分:4)

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

cout << "Hello\n";

如果在这里,你给它一个指向C风格字符串以外的东西的指针,你将得到未定义的行为。在实践中,它将逐字节地打印存储器的内容,直到它达到零值字节或走出可读存储器的末尾。

答案 1 :(得分:2)

<<上的

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

要打印地址,只需在没有演员的情况下通过&bar

答案 2 :(得分:1)

由于bar是myStruct结构的对象,它的起始地址和myStruct中第一个成员的起始地址即bar.foo将是相同的。因此&amp; bar将为您提供bar对象的起始地址,char *将为您提供该地址位置的第一个字节的值。

答案 3 :(得分:1)

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

const char * s = "hello world";

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

答案 4 :(得分:1)

std::ostream通常会为operator <<带有const char *的重载,char *将绑定到该{{1}}。

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

答案 5 :(得分:1)

如果需要输出myStruct的内容到输出流,则需要定义ostream&lt;&lt;您的结构的运算符如下:

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

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

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

希望这有帮助。

答案 6 :(得分:0)

实际上你的代码是打印struct variable bar的地址而不是foo的值。(char *)&amp; bar将struct类型的地址转换为(char *)表示c string类型。 一些c,c ++函数参数确实将struct类型作为参数,因此我们需要根据函数参数将struct类型转换为(char *)或(void *)。