以下代码段是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()中的最后一行无效。为什么这样?

最佳答案

该示例来自6.5.2.3节结构中的示例3,以及ISO/IEC 9899:2011的 union 成员。前面的段落之一是(添加了强调):



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



根据突出显示的语句,这现在很有意义。 g()中的代码使用了常见的初始序列,但仅适用于union可见且在f()中不可见的地方。

该问题也是严格的混叠之一。那是一个复杂的话题。有关详细信息,请参见What is the strict aliasing rule?

无论付出什么代价,即使在严格的警告选项下,GCC 7.1.0也不报告此问题。即使使用-Weverything选项,Clang也不会:

clang -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
    -Wstrict-prototypes -Weverything -pedantic …

关于C11相关语言的正确性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45338651/

10-11 18:53