2

我不知道为什么下面的代码工作正常,没有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,要么是限定版本,要么是对应的有符号或无符号类型,要么是字符类型。

那么,为什么允许呢?

4

1 回答 1

3

不允许。您发布的标准部分显示了您允许为对象命名的类型。

编译的代码并不意味着它是正确的。您的代码存在三个问题,导致程序表现出未定义的行为。

首先是您将 char 指针分配给 int 指针。标准不强制它们的对齐和表示,因此结果指针无效。

int  *q = (int *)p;

然后,您将char n对象解释为整数,违反了严格的别名。(请注意问题中标准的引用)。

*q;

最后,您将 anint写入 char 对象 ( ) 的内存char n,这会导致溢出,因为 an 的大小int始终大于 a 的大小char

*q = 10;
于 2014-12-23T19:24:42.460 回答