全局变量的内存布局

Memory layout of globals

考虑

Foo data[]={{...},{...},{...}};
Foo data_end={...};

如果在数组后面定义结束标记,是否保证

&data[3]==&data_end

我不想手动计算数据中的元素数量。

在没有任何优化选项的情况下,它在 gdb 中看起来还不错,但在使用它之前我需要知道编译器无法移动 data_end。如果可以,我该怎么做呢

没有。编译器以任何顺序或对齐方式放置变量并不是一个可靠的假设。对齐变量之间可能存在间隙,我已经看到编译器按字母顺序排列变量。

如果您想知道数组中不是的元素的指针,您需要知道数组元素的数量。

#define _dimof(a) (sizeof(a)/sizeof(a[0]))
Foo data[] = ... ;
// The type of the variable has been changed.
Foo* data_end = &data[_dimof(data)];

您可以删除这一段,因为添加它是为了修复代码中的语法错误。

不仅不能保证您的要求,而且符合 C++03 的实现 必须 确保 &data[3] != &data_end:

5.10 Equality operators[expr.eq]

1 … Two pointers of the same type compare equal if and only if they are both null, both point to the same object or function, or both point one past the end of the same array.

在C++11中,稍微复杂一点:

Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address (3.9.2).

3.9.2 注释:

… If an object of type T is located at an address A, a pointer of type cv T* whose value is the address A is said to point to that object, regardless of how the value was obtained. [Note: for instance, the address one past the end of an array (5.7) would be considered to point to an unrelated object of the array’s element type that might be located at that address. … —end note]

因此,新标准允许符合要求的实施 可能 在您的比较中产生 true;仍然,没有任何保证。

如果您需要计算数组元素的数量,请使用以下常用宏:

#define countof(ARR) (sizeof (ARR) / sizeof *(ARR))

或者如果你不喜欢宏,使用下面的函数:

template<class T, std::size_t N>
constexpr std::size_t countof(T (&)[N])
{
    return N;
}

但是,后一个选项需要您的编译器支持 constexpr 关键字才能与前一个选项完全等效。

不,它不可靠,在 C++11 中,就这样做

for (/* const */ Foo& foo : data) {
    // stuff with foo.
}