我试图了解6.5(p6)
中定义的严格别名规则:
和6.5(p7)
:
考虑以下示例:
struct test_internal_struct_t{
int a;
int b;
};
struct test_struct_t{
struct test_internal_struct_t tis;
};
int main(){
//alocated object, no declared type
struct test_struct_t *test_struct_ptr = malloc(sizeof(*test_struct_ptr));
//object designated by the lvalue has type int
test_struct_ptr->tis.a = 1;
//object designated by the lvalue has type int
test_struct_ptr->tis.b = 2;
//VIOLATION OF STRICT ALIASING RULE???
struct test_internal_struct_t tis = test_struct_ptr->tis;
return 0;
}
malloc(sizeof(*test_struct_ptr))
没有声明的类型,因为它已分配,如脚注87:通过
test_struct_ptr->tis.a
和test_struct_ptr->tis.b
访问的对象的有效类型为int
。但是对象test_struct_ptr->tis
自分配以来没有有效的类型。问题:
struct test_internal_struct_t tis = test_struct_ptr->tis;
是否违反严格的别名? test_struct_ptr->tis
指定的对象没有有效类型,但是lvalue
具有struct test_internal_struct_t
类型。 最佳答案
C 2018 6.5 6使用短语“通过左值存储...存储”来定义有效类型,但从不定义该短语:
因此,留给读者解释。考虑以下代码:
struct a { int x; };
struct b { int x; };
void copy(int N, struct a *A, struct b *B)
{
for (int n = 0; n < N; ++n)
A[n].x = B[n].x;
}
如果编译器知道各种对象
A[n]
不与各种对象B[n]
重叠,则它可以通过在一条指令(例如AVX或其他单指令多数据[SIMD]指令)中加载多个B[n]
来优化此代码。 ),并在一条指令中存储多个A[n]
。 (这可能需要其他代码来处理循环片段和对齐问题。此处不涉及我们。)如果对于某些不同的A[n]->x
值,某些B[n]->x
可能与n
引用同一对象,则编译器可能不会使用此类多元素加载和存储,因为它可能会更改程序的可观察行为。例如,如果情况是内存包含十个int
,其值从0到9,且B
指向0,而A
指向2:A
0 1 2 3 4 5 6 7 8 9
然后,在给定
N
= 4的情况下,编写的循环必须一次复制一个元素,从而产生:0 1 0 1 0 1 6 7 8 9
如果编译器将此优化为四元素加载和存储,则可以加载0 1 2 3然后存储0 1 2 3,从而产生:
0 1 0 1 2 3 6 7 8 9
但是,C告诉我们
struct a
和struct b
是不兼容的,即使它们的布局完全相同。当X
和Y
类型不兼容时,它告诉我们X
不是Y
。类型系统的一个重要目的是区分对象类型。现在考虑表达式
A[n]->x = B[n]->x
。在此:A[n]
是struct a
的左值。 A[n]
是.
的左操作数,因此不会将其转换为值。 A[n].x
指定并且是x
的成员A[n]
的左值。 A[n].x
中的值。 因此,直接访问存储值的对象仅在
int
成员A[n].x
中。左值A[n]
出现在表达式中,但它不是直接用于存储值的左值。 &A[n]
的有效内存类型是什么?如果我们仅将此内存解释为
int
,则对对象访问的唯一限制是所有B[n].x
均为int
而所有A[n].x
均为int
,因此部分或全部A[n].x
可以访问与部分或全部相同的内存B[n].x
,并且不允许编译器进行上述优化。这不能满足类型系统区分
struct a
和struct b
的目的,因此不能正确解释。为了实现预期的优化,必须是A[n].x
存储的内存包含struct a
对象,而B[n].x
访问的内存包含struct b
对象。因此,“通过左值存储…”必须包含这样的表达式,其中左值用于派生结构的成员,但它本身并不是用于访问的最终左值。
关于c - C中严格的别名规则,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54731678/