Is the strict aliasing rule incorrectly specified?

前端 未结 9 628
野的像风
野的像风 2020-12-29 03:50

As previously established, a union of the form

union some_union {
    type_a member_a;
    type_b member_b;
    ...
};

with n memb

9条回答
  •  梦毁少年i
    2020-12-29 04:07

    The strict aliasing rule forbids access to the same object by two pointers that do not have compatible types, unless one is a pointer to a character type:

    7 An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)

    • a type compatible with the effective type of the object,
    • a qualified version of a type compatible with the effective type of the object,
    • a type that is the signed or unsigned type corresponding to the effective type of the object,
    • a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
    • an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
    • a character type.

    In your example, *f = 1.0; is modifying fi.i, but the types are not compatible.

    I think the mistake is in thinking that a union contains n objects, where n is the number of members. A union contains only one active object at any point during program execution by §6.7.2.1 ¶16

    The value of at most one of the members can be stored in a union object at any time.

    Support for this interpretation that a union does not simultaneously contain all of its member objects can be found in §6.5.2.3:

    and if the union object currently contains one of these structures

    Finally, an almost identical issue was raised in defect report 236 in 2006.

    Example 2

    // optimization opportunities if "qi" does not alias "qd"
    void f(int *qi, double *qd) {
        int i = *qi + 2;
        *qd = 3.1;       // hoist this assignment to top of function???
        *qd *= i;
        return;
    }  
    
    main() {
        union tag {
            int mi;
            double md;
        } u;
        u.mi = 7;
        f(&u.mi, &u.md);
    }
    

    Committee believes that Example 2 violates the aliasing rules in 6.5 paragraph 7:

    "an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union)."

    In order to not violate the rules, function f in example should be written as:

    union tag {
        int mi;
        double md;
    } u;
    
    void f(int *qi, double *qd) {
        int i = *qi + 2;
        u.md = 3.1;   // union type must be used when changing effective type
        *qd *= i;
        return;
    }
    

提交回复
热议问题