C11相关语言正确性

Vik*_*dav 5 c language-lawyer c11

以下代码段是C11标准§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);
}
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*ler 6

该示例来自§6.5.2.3 结构和 ISO/IEC 9899:2011的联合成员中的示例3 .前面的一段是(重点补充):

6为了简化联合的使用,我们做了一个特殊的保证:如果一个联合包含几个共享一个共同初始序列的结构(见下文),并且如果联合对象当前包含这些结构中的一个,则允许检查它们中任何一个的共同初始部分,可以看到完整类型的联合声明.如果对应的成员具有一个或多个初始成员的序列的兼容类型(并且对于位字段,具有相同的宽度),则两个结构共享共同的初始序列.

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

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

根据突出的陈述,现在这是有道理的.代码中g()使用了公共的初始序列,但只适用于union可见且不可见的情况f().

这个问题也是严格的别名之一.这是一个复杂的话题.请参阅什么是严格别名规则?细节.

无论价值如何,即使在严格的警告选项下,GCC 7.1.0也不会报告问题.Clang也没有,即使有-Weverything选项:

clang -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
    -Wstrict-prototypes -Weverything -pedantic …
Run Code Online (Sandbox Code Playgroud)