代码之家  ›  专栏  ›  技术社区  ›  Vikas Yadav

C11相关语言正确性

  •  5
  • Vikas Yadav  · 技术社区  · 7 年前

    C11 standard §6.5.2.3

    struct t1 { int m; };
    struct t2 { int m; };
    int f(struct t1 *p1, struct t2 *p2)
    {
        if (p1->m < 0)
            p2->m = -p2->m;
        return p1->m;
    }
    int g()
    {
        union {
            struct t1 s1;
            struct t2 s2;
        } u;
        /* ... */
        return f(&u.s1, &u.s2);
    }
    

    根据C11,内部的最后一行 g() 无效。为什么会这样?

    2 回复  |  直到 6 年前
        1
  •  6
  •   Jonathan Leffler    7 年前

    该示例来自§6.5.2.3中的示例3 结构和工会成员 强调 添加):

    6为了简化联合的使用,我们做出了一项特殊保证:如果联合包含多个共享公共初始序列的结构(见下文),并且如果联合对象当前包含其中一个结构,则允许检查其中任何结构的公共初始部分 任何可以看到已完成的联合类型声明的地方 公共初始序列

    问题中引用的代码前面有注释:

    以下不是有效的片段(因为联合类型在函数中不可见 f ).

    g() 正在使用公共初始序列,但这仅适用于 union 在中可见而在中不可见 f()

    What is the strict aliasing rule? 了解详细信息。

    -Weverything 选项:

    clang -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
        -Wstrict-prototypes -Weverything -pedantic …
    
        2
  •  3
  •   Jens Gustedt    7 年前

    f

    在这里 p1 被访问两次。如果 p1 p2 应该是不同的,编译器不需要重新加载 p1 的值 return

    f 是有效代码,优化是有效的。

    g ,是无效的,因为没有看到两者可能来自同一个 union

    这是一种情况,证明调用有效性的全部责任在于函数的用户,通常没有编译器可以在以下情况下警告您: f g 碰巧在不同的翻译单位。