Is this use of unions strictly conforming?

前端 未结 4 725
攒了一身酷
攒了一身酷 2021-02-02 12:47

Given the code:

struct s1 {unsigned short x;};
struct s2 {unsigned short x;};
union s1s2 { struct s1 v1; struct s2 v2; };

static int read_s1x(struct s1 *p) { re         


        
4条回答
  •  半阙折子戏
    2021-02-02 13:24

    With a strict interpretation of the standard, this code might be not conforming. Let's focus on the text of the well-known §6.5p7:

    An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
    — 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.

    (emphasis mine)

    Your functions read_s1x() and write_s2x() do the opposite of what I marked bold above in the context of your whole code. With just this paragraph, you could conclude that it's not allowed: A pointer to union s1s2 would be allowed to alias a pointer to struct s1, but not vice versa.

    This interpretation of course would mean that the code must work as intended if you "inline" these functions manually in your test(). This is indeed the case here with gcc 6.2 for i686-w64-mingw32.


    Adding two arguments in favor of the strict interpretation presented above:

    • While it's always allowed to alias any pointer with char *, a character array can't be aliased by any other type.

    • Considering the (here unrelated) §6.5.2.3p6:

      One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible.

      (again emphasis mine) -- the typical interpretation is that being visible means directly in the scope of the function in question, not "somewhere in the translation unit" ... so this guarantee doesn't include a function that takes a pointer to one of the structs that's a member of the union.

提交回复
热议问题