我不知道为什么以下代码正常,没有gcc
错误(-fstrict-aliasing -Wstrict-aliasing=1
)。
#include <stdio.h>
int
main(void)
{
char n = 42;
char *p = &n;
int *q = (int *)p;
*q = 10;
printf("%d|%d\n", *p, *q);
return 0;
}
如果我遵循严格的别名规则:
n1570,§6.5表达式
对象的存储值只能由左值访问 具有以下类型之一的表达式:
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本
- 对应于有效类型的有符号或无符号类型 对象,
- 对应于对象有效类型的限定版本的有符号或无符号类型,
- 聚合或联合类型,其成员中包含上述类型之一(包括递归地,子聚合或包含联合的成员),或
- 字符类型。
但是*q
没有与*p
兼容的类型,无论是合格版本,还是对应的有符号或无符号类型,都是字符类型。
那么,为什么允许这样做?
答案 0 :(得分:3)
不允许。您发布的标准部分显示了您允许使用别名对象的类型。
编译代码的事实并不意味着它是正确的。您遇到的代码存在三个问题,导致程序显示未定义的行为。
首先,您指定了一个指向int指针的char指针。 标准没有强制执行它们的对齐和表示,因此结果指针无效。
int *q = (int *)p;
然后您将char n
对象解释为整数,违反严格别名。(请注意问题中标准的引用)。
*q;
最后你在char对象(int
)的内存中写了一个char n
,这会导致溢出,因为int
的大小总是大于{{}的大小1}}。
char