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 *)会导致数据以逐字节的方式排列,但是这不应该影响地址吗?
答案 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 *)。