为什么不显示char数据的地址?

50 c++ cout memory-address

class Address {
      int i ;
      char b;
      string c;
      public:
           void showMap ( void ) ;
};

void Address :: showMap ( void ) {
            cout << "address of int    :" << &i << endl ;
            cout << "address of char   :" << &b << endl ;
            cout << "address of string :" << &c << endl ;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

         address of int    :  something
         address of char   :     // nothing, blank area, that is nothing displayed
         address of string :  something 
Run Code Online (Sandbox Code Playgroud)

为什么?

另一个有趣的事情:如果int,char,string是公共的,那么输出就是

  ... int    :  something 
  ... char   :   
  ... string :  something_2
Run Code Online (Sandbox Code Playgroud)

something_2 - something总是等于8. 为什么?(不是9)

hrn*_*rnt 82

当你拿到b的地址时,你得到了char *.operator<<将其解释为C字符串,并尝试打印字符序列而不是其地址.

试着cout << "address of char :" << (void *) &b << endl改为.

[编辑]像Tomek评论的那样,在这种情况下使用更合适的演员阵容static_cast,这是一个更安全的选择.这是一个使用它而不是C风格的强制转换的版本:

cout << "address of char   :" << static_cast<void *>(&b) << endl;
Run Code Online (Sandbox Code Playgroud)

  • 你能举例说明为什么static_cast是一种更安全的替代品吗?我不明白在这里使用void*有什么害处. (2认同)
  • @VishalSharma是的,避免使用C样式强制转换是一个好习惯。在这种特殊情况下的行为将是相同的。在其他情况下,`&`可能已经超载(因此您没有得到“地址”),或者您可能在做一些“ const” /“ volatile”正确性很重要的事情,或者,或者,或者,或者 (2认同)

Cas*_*Cow 26

有两个问题:

  • 为什么它不打印char的地址:

打印指针将打印地址int*string*,但不会对打印内容char*,因为在一个特殊的过载operator<<.如果你想要地址,那么使用:static_cast<const void *>(&c);

  • 为什么之间的地址差intstring8

在你的平台sizeof(int)4sizeof(char)1让你真正应该问为什么85.原因是字符串在4字节边界上对齐.机器使用单词而不是字节,并且如果单词因此不是"分割"在这里的几个字节和那里的几个字节,则工作得更快.这称为对齐

您的系统可能与4字节边界对齐.如果您的64位系统具有64位整数,则差异为16.

(注意:64位系统通常是指指针的大小,而不是int.因此,具有4字节int的64位系统仍然会有8的差异,因为4 + 1 = 5但是最多为8如果sizeof(int)是8那么8 + 1 = 9但这最多可以达到16)


Ton*_*roy 13

当您将char的地址流式传输到ostream时,它会将其解释为ASCIIZ"C-style"字符串的第一个字符的地址,并尝试打印假定的字符串.您没有NUL终结器,因此输出将继续尝试从内存中读取,直到找到一个或操作系统关闭它以尝试从无效地址读取.它扫描的所有垃圾都将被发送到您的输出.

您可以通过投射来显示所需的地址,例如(void*)&b.

将偏移量重新放入结构中:您观察到字符串位于偏移量8.这可能是因为您有32位整数,然后是8位字符,然后编译器选择再插入3个8位字符,以便字符串对象将在32位字边界处对齐.许多CPU /内存架构需要指针,整数等在字大小的边界上对它们执行有效的操作,否则必须做更多的操作来从内存中读取和组合多个值,然后才能使用这些值在一次行动中.根据您的系统,可能每个类对象都需要从单词边界开始,或者std::string特别是可能需要以size_t,指针或需要这种对齐的其他类型开始.


peo*_*oro 10

因为当你传递char*std::ostream它时,它将打印char*它所指向的C风格(即:char数组)字符串.

记住那"hello"是一个char*.

  • "你好"是一个`const char [6]`. (7认同)
  • @MSalters:不。它是“char[6]”,使用时会在“char*”中衰减。 (2认同)
  • 它只是在C中的`char [6]`,但在C++中它是`const char [6]`.有趣的是,它仍然可以腐烂到`char*`(向后与C兼容). (2认同)