问题:
下面的代码是否违反了严格别名规则?也就是说,一台聪明的编译器是否允许打印
00000
(或其他一些不好的效果),因为缓冲区首先作为其他类型进行访问,然后通过int*
访问?如果不是,那将只移动
ptr2
的定义和初始化到大括号之前(这样当ptr1
进入范围时,ptr2
就已经被定义了)会破坏它吗?如果不是,那将去掉大括号(这样
ptr1
和ptr2
将在同一范围内),这会破坏它吗?如果是,该如何修复代码?
奖励问题:如果代码没有问题,2 或 3 不会破坏它,如何更改以使其违反严格别名规则(例如,将大括号循环转换为使用 int16_t
)?
int i;
void *buf = calloc(5, sizeof(int)); // buf initialized to 0
{
char *ptr1 = buf;
for(i = 0; i < 5*sizeof(int); ++i)
ptr1[i] = i;
}
int *ptr2 = buf;
for(i = 0; i < 5; ++i)
printf("%d", ptr2[i]);
寻求确认,需要一份简短的专家答案来解释这段特定代码,最好不要使用大量标准引用。我只需要与此代码相关的部分,不需要对严格别名规则进行长时间的解释。如果答案能明确列出上面编号的问题,那就太好了。另外,假设使用通用CPU,没有整数陷阱值,还假设int
是32位的二进制补码。
int
,因为根据“对于没有声明类型的对象的所有其他访问,对象的有效类型仅是用于访问的 lvalue 的类型。” - 2501int
到对象中,而不是读取,类型也会变成int
,因为:如果通过具有非字符类型的 lvalue 存储值到没有声明类型的对象中,则该 lvalue 的类型成为该访问和后续访问的对象的有效类型,这些后续访问不修改存储的值。 - 2501for
循环。第7段中的“一个字符类型”从句是必要的,以避免违反严格别名规则。 - Andrew Henleint
与char
不兼容。 - 2501