为了澄清问题,请观察c/c++代码片段:
int a = 10, b = 20, c = 30, d = 40; //consecutive 4 int data values.
int* p = &d; //address of variable d.
现在,在 Visual Studio(2013 年测试)中,如果 p == hex_value 的值(可以在调试器内存窗口中查看),那么,您可以观察到其他变量 a、b、c 的地址,和 d 各相差 12 字节!
所以,如果 p == hex_value
,则如下:
&c == hex_value + 0xC
(注意十六进制 C 是十进制的 12)
&b == &c + 0xC
&a == &b + 0xC
那么,为什么会有 12 个字节的偏移而不是 4 个字节—— int 只是 4 个字节?
现在,如果我们声明一个数组:
int array[] = {10,20,30,40};
值 10, 20, 30, 40 与预期的相差 4 个字节!
谁能解释一下这种行为?
最佳答案
标准 C++ 在 8.3.4 数组 节中声明,“数组类型的对象包含一个连续分配的非空集,由 N 个 T 类型的子对象组成。”
这就是为什么 array[]
将是一组连续的 int
,并且一个元素和下一个元素之间的差异将恰好是 sizeof(int)。
对于本地/ block 变量(自动存储),不提供这样的保证。唯一的陈述在 1.7 节中。 C++ 内存模型:“每个字节都有一个唯一的地址。” 和 1.8。 C++ 对象模型:“该对象的地址是它占用的第一个字节的地址。两个对象 (...) 应具有不同的地址”。
因此,假设此类对象的连续性所做的一切都是未定义的行为且不可移植。您甚至无法确定创建这些对象的地址的顺序。
现在我已经使用了你的代码的修改版本:
int a = 10, b = 20, c = 30, d = 40; //consecutive 4 int data values.
int* p = &d; //address of variable d.
int array[] = { 10, 20, 30, 40 };
char *pa = reinterpret_cast<char*>(&a),
*pb = reinterpret_cast<char*>(&b),
*pc = reinterpret_cast<char*>(&c),
*pd = reinterpret_cast<char*>(&d);
cout << "sizeof(int)=" << sizeof(int) << "\n &a=" << &a << \
" +" << pa - pb << "char\n &b=" << &b << \
" +" << pb - pc << "char\n &c=" << &c << \
" +" << pc - pd << "char\n &d=" << &d;
memset(&d, 0, (&a - &d)*sizeof(int));
// ATTENTION: undefined behaviour:
// will trigger core dump on leaving
// "Runtime check #2, stack arround the variable b was corrupted".
运行此代码时,我得到:
debug release comment on release
sizeof(int)=4 sizeof(int)=4
&a=0052F884 +12char &a=009EF9AC +4char
&b=0052F878 +12char &b=009EF9A8 +-8char // is before a
&c=0052F86C +12char &c=009EF9B0 +12char // is just after a !!
&d=0052F860 &d=009EF9A4
所以你看到地址的顺序甚至可以在同一个编译器上改变,这取决于构建选项!事实上,在 Release模式下,变量是连续的,但顺序不同。
调试版的多余空格来自选项/RTCs .我故意用苛刻的 memset() 覆盖变量,假设它们是连续的。退出执行后,我立即收到一条消息:“运行时检查 #2,围绕变量 b 的堆栈已损坏”,这清楚地表明了这些额外字符的用途。
如果您删除该选项,您将获得 MSVC13 连续变量,每个 4 个字节,如您所料。但是也不会再有关于堆栈损坏的错误消息。
关于visual-studio - 为什么在 Visual Studio 中连续的 int 数据类型变量位于 12 字节偏移处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25442458/