非数组复合成员间的字节指针偏移计算是否有定义?
复合对象成员指针相减的行为疑问
我理解C++标准expr.add#4.2条款中,将+和-操作限制为指向同一数组元素的指针的原因,这在我之前关于偏移指针类的问题评论中已有解释。但类似操作也可在同一(嵌套)复合对象的成员间完成,不一定局限于数组。若此类偏移结果不确定,offsetof宏便失去意义。
以下是类比offsetof的示例:
#include <iostream> #include <cstddef> struct Inner { int i1; float f; bool b; int i2; }; struct Outer { int i1; char c; int i2; Inner inner; double d; }; int main(int argc, char* argv[]) { Outer outer; std::cout << "reinterpret_cast<std::byte*>(&outer.i2) - reinterpret_cast<std::byte*>(&outer.i1): " << reinterpret_cast<std::byte*>(&outer.i2) - reinterpret_cast<std::byte*>(&outer.i1) << std::endl; std::cout << "reinterpret_cast<std::byte*>(&outer.inner.i2) - reinterpret_cast<std::byte*>(&outer.i1): " << reinterpret_cast<std::byte*>(&outer.inner.i2) - reinterpret_cast<std::byte*>(&outer.i1) << std::endl; std::cout << "offsetof(Outer, i2) - offsetof(Outer, i1): " << offsetof(Outer, i2) - offsetof(Outer, i1) << std::endl; std::cout << "offsetof(Outer, inner) + offsetof(Inner, i2) - offsetof(Outer, i1): " << offsetof(Outer, inner) + offsetof(Inner, i2) - offsetof(Outer, i1) << std::endl; return 0; }
运行结果:
reinterpret_cast<std::byte*>(&outer.i2) - reinterpret_cast<std::byte*>(&outer.i1): 8 reinterpret_cast<std::byte*>(&outer.inner.i2) - reinterpret_cast<std::byte*>(&outer.i1): 24 offsetof(Outer, i2) - offsetof(Outer, i1): 8 offsetof(Outer, inner) + offsetof(Inner, i2) - offsetof(Outer, i1): 24
所有涉及的指针目标都在outer对象内,但并非同一对象。这属于未定义行为吗?
(经评论后编辑:非字节指针在混合类型复合对象中会失效,且C++标准expr.add#4.2条款中的"假设"无法满足我的需求,感谢!)
支持其为定义行为的论据:
- 指针转换为
std::byte、char和unsigned char类型的操作在严格别名规则限制下是有定义的。 - 指向外部复合对象的字节指针指向代表整个复合对象的字节数组A的第一个元素。
offsetof的语义要求所有复合成员在复合对象内有固定偏移。- 因此,所有转换为字节指针的复合成员指针也指向数组A的元素。
内容的提问来源于stack exchange,提问作者Michael Steffens
相关产品推荐
相关产品推荐

