简体   繁体   English

是否从 C 标准定义的同一联合中的不同成员分配给联合成员?

[英]Is assigning to a union member from a different member in the same union defined by the C standard?

Consider:考虑:

union { int i; char c; } x = {0};
x.c = x.i;

C 2018 6.15.16.1 3, about simple assignment, says: C 2018 6.15.16.1 3,关于简单赋值,说:

If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type;如果存储在 object 中的值是从另一个 object 读取的,该 object 以任何方式与第一个 object 的存储重叠,则重叠应准确,并且两个对象应具有兼容的版本; otherwise, the behavior is undefined.否则,行为未定义。

x.c and xi overlap but not exactly and do not have versions of a compatible type. x.cxi重叠但不完全重叠,并且没有兼容类型的版本。 So is the behavior of this assignment not defined by the C standard?那么 C 标准没有定义此分配的行为吗?

In my opinion, you've found a flaw in the standard.在我看来,你发现了标准中的一个缺陷。 I think the intent is that x.c = xi;我认为意图是x.c = xi; has undefined behavior, but that passage (which has been in the standard since C90) does not correctly express that intent.具有未定义的行为,但该段落(自 C90 以来一直在标准中)没有正确表达该意图。

That wording applies to simple assignment.该措辞适用于简单的分配。 In a simple assignment, the LHS must be an lvalue, and the RHS is just an expression.在简单的赋值中,LHS 必须是一个左值,而 RHS 只是一个表达式。 If the RHS happens to be an lvalue, it undergoes lvalue conversion as described in 6.3.2.1p2.如果 RHS 恰好是一个左值,它会按照 6.3.2.1p2 中的描述进行左值转换 After lvalue conversion, it is no longer an lvalue.左值转换后,不再是左值。

It would be reasonable to say that an assignment that copies one object to another object has undefined behavior when the objects overlap (unless the overlap is exact and the objects have compatible type).可以合理地说,当对象重叠时,将一个 object 复制到另一个 object 的分配具有未定义的行为(除非重叠是精确的并且对象具有兼容的类型)。 But assignment does not operate on two objects;但是赋值不对两个对象进行操作; it operates on an object (the LHS) and a non-lvalue expression (the RHS).它在 object(LHS)和非左值表达式(RHS)上运行。

The passage says that the value "is read from another object".该段落说该值“是从另一个对象中读取的”。 That's ambiguous.这是模棱两可的。 Must name of the object be the entire RHS expression, or can it be just a subexpression? object 的名称必须是整个 RHS 表达式,还是只能是一个子表达式? If the latter, then x.c = xi + 1;如果是后者,那么x.c = xi + 1; would have undefined behavior, which in my opinion would be absurd.会有未定义的行为,在我看来这是荒谬的。

As written, the conditions given in the quoted passage cannot occur.正如所写,引用段落中给出的条件不会发生。

If the passage were to be corrected, it should apply only when the RHS is an lvalue (before lvalue conversion), and would discuss overlap between the object designated by the LHS and the object designated by the RHS.如果要更正该段落,则仅当 RHS 为左值时(左值转换之前)才适用,并且将讨论 LHS 指定的 object 与 RHS 指定的 object 之间的重叠。

The specific case here, assigning overlapping small integer objects, is not likely to cause problems in practice, but we could construct cases that are more problematic.这里的具体情况,分配重叠的小 integer 对象,在实践中不太可能导致问题,但我们可以构建更成问题的情况。 For example:例如:

int main() {
    struct big {
        int array[1000];
    };

    struct big_wrapper {
        int n;
        struct big b;
    };


    union u {
        struct big x;
        struct big_wrapper y;
    };

    union u obj;
    obj.x = obj.y.b;
}

Here the assignment copies the value of one large object into another large object, where the two objects overlap but do not start at the same location.这里的赋值将一个大 object 的值复制到另一个大 object 中,其中两个对象重叠但不在同一位置开始。 To implement this correctly, a compiler would have to detect the overlap and perhaps generate a call to memmove() or equivalent.为了正确实现这一点,编译器必须检测重叠并可能生成对memmove()或等效的调用。 And the overlap might not be directly visible if the assignment is performed via pointers.如果通过指针执行分配,重叠可能不会直接可见。 Making the behavior undefined allows compilers to generate efficient code for the non-overlapping cases.使行为未定义允许编译器为不重叠的情况生成有效的代码。

The intent, I believe, is that this assignment also has undefined behavior but again the lvalue conversion means that that intent is not clearly expressed.我相信,其意图是该赋值也具有未定义的行为,但左值转换再次意味着该意图没有明确表达。

In my opinion, that passage should be updated to state that it applies when the RHS is an lvalue, and that the relevant objects are the LHS and the pre-conversion RHS.在我看来,该段落应该更新为 state,它适用于 RHS 是左值时,并且相关对象是 LHS 和转换前 RHS。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM