为什么这些变量的地址打印为ab @和b @?

时间:2014-01-06 02:32:44

标签: c++ memory-address

我运行以下代码:

    #include <iostream>

    using namespace std;

    typedef struct Test
    {
        char   a;
        char   b;
        int    i;
        double d;
    }Test;

    int main()
    {
        Test test;
        test.a = 'a';
        test.b = 'b';
        test.i = 478;
        test.d = 4.7;

        cout << &test.a << '\n'
             << &test.b << '\n'
             << &test.i << '\n'
             << &test.d << '\n';

        return 0;
    }

输出结果为:

    ab@
    b@
    0x28fe94
    0x28fe98

起初,我认为这是&.之间优先的结果。
但是0x28fe940x28fe94表明它不是优先问题 我可以弄清楚ab@b@是什么意思?

3 个答案:

答案 0 :(得分:5)

写作时

 cout << &test.a

因为test.achar,这会调用operator<< (ostream&, const char*)重载,认为你的char*是指向C风格字符串的指针,而不是指向只有一个角色。因此,操作将从&test.a的存储器地址开始读取字节,直到找到空终止符(零字节)。打印出ab@时会发生这种情况,因为a的值为'a'b的值为'b',而系统上的数字478恰好对应到一个@字符,最后是一个空字节。

如果您想查看test.atest.b的数字地址,请将指针转换为void* s,这将选择operator<< (ostream&, const void*)重载。例如:

cout << static_cast<void*>(&test.a)

希望这有帮助!

答案 1 :(得分:3)

这意味着未定义的行为。 const char *有一个特殊的重载,它将它打印为以null结尾的字符串。你的没有终结者,所以它超越并触发了前面提到的UB。修复它:

std::cout << static_cast<void *>(&test.a) << '\n'
          << static_cast<void *>(&test.b) << '\n'
          << &test.i << '\n'
          << &test.d << '\n';

答案 2 :(得分:1)

因为您在使用&test.a&test.b时传递了字符的地址,所以cout运算符将地址视为字符串的开头。这就是您首先获得ab@然后b@的原因。 @不太明显;它落在两个char值之后和结构中int值之前的填充中,并且是准随机垃圾。您实际上是在调用未定义的行为,因为您要求输出代码访问填充。如果要打印地址,请转换为void *。如果要打印字符,请不要提供地址。