以下代码段是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/