考虑
Foo data[]={{...},{...},{...}};
Foo data_end={...};
如果结束标记是在数组之后定义的,是否可以保证
&data[3]==&data_end
我不想手动计算数据中元素的数量。
它碰巧在 gdb 中看起来不错,没有任何优化选项,但在使用它之前,我需要知道编译器无法移动data_end
. 如果可以,我该怎么做。
考虑
Foo data[]={{...},{...},{...}};
Foo data_end={...};
如果结束标记是在数组之后定义的,是否可以保证
&data[3]==&data_end
我不想手动计算数据中元素的数量。
它碰巧在 gdb 中看起来不错,没有任何优化选项,但在使用它之前,我需要知道编译器无法移动data_end
. 如果可以,我该怎么做。
不仅不能保证您的要求,而且符合 C++03 的实现必须确保&data[3] != &data_end
:
5.10 等式运算符[expr.eq]
1 ... 两个相同类型的指针比较相等当且仅当它们都为空,都指向同一个对象或函数,或者都指向同一个数组的末尾之后。
在 C++11 中,它有点复杂:
相同类型的两个指针比较相等当且仅当它们都为空,都指向同一个函数,或都表示相同的地址(3.9.2)。
3.9.2 注意事项:
…如果一个类型的对象
T
位于一个地址,那么一个值为该地址的cvA
类型的指针被称为指向该对象,而不管该值是如何获得的。[注意:例如,数组末尾的地址(5.7)将被视为指向可能位于该地址的数组元素类型的不相关对象。……——尾注]T*
A
因此,新标准允许符合要求的实现在您的比较中可能会产生正确的结果;仍然没有任何保证。
如果需要计算数组的元素个数,请使用以下 stock 宏:
#define countof(ARR) (sizeof (ARR) / sizeof *(ARR))
或者,如果您不喜欢宏,请使用以下函数:
template<class T, std::size_t N>
constexpr std::size_t countof(T (&)[N])
{
return N;
}
但是,后一种选择需要您的编译器支持constexpr
关键字与前一种完全等效。
不,编译器以任何顺序或任何对齐方式放置变量不是一个可靠的假设。对齐变量之间可能存在间隙,我已经看到编译器按字母顺序排列变量。
如果您想知道指向不在数组中的元素的指针,您需要知道数组元素的数量。
#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++11 中,只需执行
for (/* const */ Foo& foo : data) {
// stuff with foo.
}