所有变量都根据它们在程序中声明的顺序连续存储吗?

are all variables stored contiguously based on the order in which they are declared in the program?

我正在学习数组以及当您尝试写入越界时它如何对您的程序有害。发现这一点后,我尝试越界读取。

我玩弄了一个字符数组和一个字符变量。

   //this occurs within int main()

   char vowels[]{'a', 'e', 'i', 'o', 'u'};
   char x = 'x';

   std::cout << vowels[5]; //this outputs x

这让我想知道是否所有变量都按照声明的顺序连续存储。

this made me wonder if all variables are stored contiguously in the order in which they are declared

不,在这种情况下,C++ 唯一保证的是,当您使用变量名读取值时,您将获得它。它们存储在内存中的顺序,或者即使它们存储在内存中的顺序都无法保证,这样做对您来说最糟糕的事情 - 越界访问实际上会使您的整个程序无效,并且从语言的角度来看,您无法期望您程序中的任何内容。

从标准 (7.6.9.4) :

The result of comparing unequal pointers to objects is defined in terms of a partial order consistent with the following rules:

  • If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript is required to compare greater.

  • If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member is required to compare greater provided the two members have the same access control ([class.access]), neither member is a subobject of zero size, and their class is not a union.

  • Otherwise, neither pointer is required to compare greater than the other.

由于前两个子句不适用于比较 x 的地址与 vowels 的地址或其元素,因此它们的地址没有有意义的可比性。

但在这种情况下,指针 vowels + 5vowels[5] 尝试取消引用的地址)具有特殊含义。任何指向具有 n 元素的数组的索引 n 处的假设元素的指针都称为“结束指针之后的指针”。它代表数组末尾后的第一个字节。允许计算此地址但不能取消引用它。该标准有一条注释,明确指出您根本不能使用 vowels[5] (6.8.2.3) :

[...] A pointer past the end of an object ([expr.add]) is not considered to point to an unrelated object of the object's type that might be located at that address. [...]

因此,即使 x 恰好位于 vowels + 5,您仍然无法通过 vowels[5].

访问它

this made me wonder if all variables are stored contiguously in the order in which they are declared.

没有,或者至少语言没有指定它(参见 François Andrieux 的 )。变量在内存中的布局(特别是堆栈上的非成员变量)由编译器自行决定。由于编译器必须处理诸如对齐之类的体系结构要求,因此它可以重新排列变量并在它们之间留下间隙。这对于优化很重要。

这是一个示例 (x86-64),其中编译器 (clang-9) 不按声明顺序布置变量...

#include <iostream>

int main() {

  char a[] {'a', 'b'};
  int x;

  std::cout << "&a[0] = " << (void*) &a[0] << std::endl;
  std::cout << "&a[1] = " << (void*) &a[1] << std::endl;
  std::cout << "&x = " << &x << std::endl;

  return 0;
}
&a[0] = 0x7ffd5becf02a
&a[1] = 0x7ffd5becf02b
&x = 0x7ffd5becf024