不管代码有多“糟糕”,并且假设对齐等在编译器/平台上不是问题,这是未定义或损坏的行为吗?
如果我有这样的结构:-
struct data
{
int a, b, c;
};
struct data thing;
Is it legal to access a
, b
and c
as (&thing.a)[0]
, (&thing.a)[1]
, and (&thing.a)[2]
?
在每种情况下,在我尝试过的每个编译器和平台上,我尝试过的每个设置都“有效”。我只是担心编译器可能没有意识到 b 和 thing[1] 是同一个东西,并且存储到 ‘b’ 的内容可能会放在一个寄存器中,而 thing[1] 从内存中读取错误的值(例如)。在每种情况下,我都尝试过它做了正确的事情。 (我当然意识到这并不能证明太多)
这不是我的代码;这是我必须使用的代码,我对这是 坏 代码还是 损坏 代码感兴趣,因为不同之处会影响我对其进行大量更改的优先级:)
标记 C 和 C++ 。我对 C++ 最感兴趣,但如果 C 不同,我也对 C 感兴趣,只是为了感兴趣。
原文由 jcoder 发布,翻译遵循 CC BY-SA 4.0 许可协议
这是非法的1 。这是 C++ 中的未定义行为。
您正在以数组方式获取成员,但这是 C++ 标准所说的(强调我的):
但是,对于成员来说,没有这样的 连续 要求:
虽然上面的两个引号应该足以暗示为什么索引到
struct
不是 C++ 标准定义的行为,让我们举一个例子:看看表达式(&thing.a)[2]
- 关于下标运算符:深入研究上面引用的粗体文本:关于将整数类型添加到指针类型(注意这里的重点)..
注意 if 子句的 数组 要求; 否则 在上面的引用中。表达式
(&thing.a)[2]
显然不符合 if 子句的条件;因此,未定义的行为。附带说明:虽然我已经在各种编译器上对代码及其变体进行了广泛的试验,但它们在这里没有引入任何填充,(它 _有效_);从维护的角度来看,代码是极其脆弱的。在执行此操作之前,您仍然应该断言实现连续分配成员。并保持在界内:-)。但它仍然是未定义的行为….
其他答案提供了一些可行的解决方法(具有定义的行为)。
正如评论中正确指出的那样,我之前编辑的 [basic.lval/8] 不适用。谢谢@2501 和@MM
1 :请参阅@Barry 对此问题的回答,了解您可以通过此部分访问
thing.a
结构成员的唯一一个法律案例。