为什么Visual Studio中的连续int数据类型变量位于12个字节偏移?

要澄清这个问题,请观察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 (注意hexC是十进制的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)。

对于本地/块变量(自动存储),不提供此类保证。 唯一的陈述在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(&a), *pb = reinterpret_cast(&b), *pc = reinterpret_cast(&c), *pd = reinterpret_cast(&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 

所以你看到地址的顺序甚至可以在同一个编译器上改变,具体取决于构建选项! 事实上,在发布模式下,变量是连续的,但不是以相同的顺序。

调试版本上的额外空格来自选项/ RTC 。 我故意用苛刻的memset()覆盖变量,假设它们是连续的。 退出执行后,我立即得到一条消息: “运行时检查#2,堆栈周围变量b已损坏” ,这清楚地说明了这些额外字符的用途。
如果删除该选项,您将获得MSVC13连续变量,每个变量都是您所期望的4个字节。 但是不会有关于堆栈损坏的错误消息。