关于char和严格别名的通用指针
我不知道为什么下面的代码工作正常,没有gcc
错误( -fstrict-aliasing -Wstrict-aliasing=1
)。
#include 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
兼容的类型,无论是合格版本,还是对应的有符号或无符号类型,都是字符类型。
那么,为什么允许这样做呢?
这个不允许。 您发布的标准部分显示了允许别名对象的类型。
编译代码的事实并不意味着它是正确的。 您遇到的代码存在三个问题,导致程序显示未定义的行为。
首先,您指定了一个指向int指针的char指针。 Standard不会强制执行它们的对齐和表示,因此生成的指针无效。
int *q = (int *)p;
然后,您将char n
对象解释为整数,违反严格别名。(请注意问题中标准的引用)。
*q;
最后你在char对象( char n
)的内存中写了一个int
,这会导致溢出,因为int
的大小总是大于char
大小。
*q = 10;