索引到结构是否合法? [英] Is it legal to index into a struct?

查看:55
本文介绍了索引到结构是否合法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不管代码有多糟糕,并假设编译器/平台上都不存在对齐等问题,这是未定义的还是损坏的行为?

Regardless of how 'bad' the code is, and assuming that alignment etc are not an issue on the compiler/platform, is this undefined or broken behavior?

如果我有这样的结构:-

If I have a struct like this :-

struct data
{
    int a, b, c;
};

struct data thing;

访问 a是法律 code>, b c 作为(&thing.a)[ 0] (& thing.a)[1] (& thing.a)[2] ]

Is it legal to access a, b and c as (&thing.a)[0], (&thing.a)[1], and (&thing.a)[2]?

在每种情况下,在我尝试过的每个编译器和平台上,我尝试过的所有设置都有效。我只是担心编译器可能不会意识到 b thing [1] 是同一件事,而存储到'b'的内容可能会放在寄存器中[1]从内存中读取错误的值(例如)。在每种情况下,我都尝试过它做对了。 (我当然知道不会证明什么)

In every case, on every compiler and platform I tried it on, with every setting I tried it 'worked'. I'm just worried that the compiler might not realize that b and thing[1] are the same thing and stores to 'b' might be put in a register and thing[1] reads the wrong value from memory (for example). In every case I tried it did the right thing though. (I realize of course that doesn't prove much)

这不是我的代码;它是我必须使用的代码,我对这是代码还是残破代码感兴趣,因为不同之处会影响我对其进行大量更改的优先级:)

This is not my code; it's code I have to work with, I'm interested in whether this is bad code or broken code as the different affects my priorities for changing it a great deal :)

标记为C和C ++。我主要对C ++感兴趣,但也对C感兴趣,只是出于兴趣。

Tagged C and C++ . I'm mostly interested in C++ but also C if it is different, just for interest.

推荐答案

这是非法的 1 。在C ++中,这是未定义的行为。

It is illegal 1. That's an Undefined behavior in C++.

您正在以数组方式接收成员,但这是C ++标准所说的(强调我的意思):

You are taking the members in an array fashion, but here is what the C++ standard says (emphasis mine):


[dcl.array / 1] ... ...数组类型的对象包含一个连续分配的N类型的N
个子对象的非空集合。 ..

[dcl.array/1]: ...An object of array type contains a contiguously allocated non-empty set of N subobjects of type T...

但是,对于成员来说,没有这样的连续要求:

But, for members, there's no such contiguous requirement:


[class .mem / 17] ...;实施对齐要求可能导致两个相邻的
成员不能彼此立即分配
...

虽然以上两个引号足以暗示为什么索引为 struct 您不是C ++标准定义的行为d,我们举一个例子:看一下表达式(& thing.a)[2] -关于下标运算符:

While the above two quotes should be enough to hint why indexing into a struct as you did isn't a defined behavior by the C++ standard, let's pick one example: look at the expression (&thing.a)[2] - Regarding the subscript operator:


> expr.post//expr.sub/1]
在后缀表达式后跟方括号的表达式是
后缀表达式。其中一个表达式是
类型的glvalue T的数组或指向T的指针类型的prvalue,另一个表达式
是无范围枚举或整数类型的prvalue。结果是类型为 T的
。类型 T应为完全定义的对象类型。66
表达式 E1 [E2] 与<$相同(根据定义) c $ c>(((E1)+(E2))

[expr.post//expr.sub/1]: A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall be a glvalue of type "array of T" or a prvalue of type "pointer to T" and the other shall be a prvalue of unscoped enumeration or integral type. The result is of type "T". The type "T" shall be a completely-defined object type.66 The expression E1[E2] is identical (by definition) to ((E1)+(E2))

上面的引号的粗体字:关于将整数类型添加到指针类型(请注意此处的重点)。

Digging into the bold text of the above quote: regarding adding an integral type to a pointer type (note the emphasis here)..


< a href = http://eel.is/c++draft/expr.add#4 rel = noreferrer> [expr.add / 4] :将整数类型添加到
指针或从中减去,结果将具有指针操作数的类型。 如果
表达式 P 指向<的元素 x [i] strong> 一个数组对象 x
具有n个元素,表达式 P + J J + P (其中 J
值为 j )指向(可能是假设的)元素 x [i + j]
(如果 0≤i + j≤n 否则,该行为未定义。 ...

[expr.add/4]: When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i + j] if 0 ≤ i + j ≤ n; otherwise, the behavior is undefined. ...

请注意 if 子句的 array 要求;否则上述报价中的否则(& thing.a)[2] 表达式显然不符合 if 子句;因此,未定义行为。

Note the array requirement for the if clause; else the otherwise in the above quote. The expression (&thing.a)[2] obviously doesn't qualify for the if clause; Hence, Undefined Behavior.

虽然我已经在各种编译器和他们在这里没有引入任何填充,(有效);从维护的角度来看,该代码非常脆弱。您仍应断言在执行此操作之前,实现已连续分配了成员。并保持边界:-)。但是它的行为仍然不确定。...

On a side note: Though I have extensively experimented the code and its variations on various compilers and they don't introduce any padding here, (it works); from a maintenance view, the code is extremely fragile. you should still assert that the implementation allocated the members contiguously before doing this. And stay in-bounds :-). But its still Undefined behavior....

其他答案也提供了一些可行的解决方法(具有定义的行为)。

Some viable workarounds (with defined behavior) have been provided by other answers.

正如评论中正确指出的, [basic.lval / 8] (不适用于我先前的编辑)。感谢@ 2501和@MM

As rightly pointed out in the comments, [basic.lval/8], which was in my previous edit doesn't apply. Thanks @2501 and @M.M.

1 :只有一个可以访问<$ c的法律案例,请参见@Barry对这个问题的回答。 $ c> thing.a 成员通过此方式。

1: See @Barry's answer to this question for the only one legal case where you can access thing.a member of the struct via this parttern.

这篇关于索引到结构是否合法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆