首页 > 解决方案 > 如何指示结构成员没有别名?

问题描述

如果您编写如下语句:

a[i] = b[i] + c[i];

...您可能希望向编译器指示a[i]b[i]c[i]指向内存中的不同位置,从而启用各种优化(例如矢量化)。这可以通过在声明中添加特殊关键字来完成:

float * __restrict__ a; // same for b and c

float但是,如果不是使用更复杂的对象,你会怎么做,比如:

struct item {
    float foo, bar;
};

考虑以下代码:

float *a, *b;
item *c;
// ...
for (int i = 0; i < 42; ++i) {
    a[i] = b[i] * c[i].foo + c[i].bar;
}

在循环中,编译器不关心,c[i]而是关心c[i].fooand c[i].bar。在这种情况下,如何针对结构的各个字段声明关于指针独立性的等效断言?

标签: c++gccstrict-aliasingrestrict

解决方案


该标准不要求编译器适应a[anything]并且b[anything]可能用于访问struct item. 它列出了实现必须始终允许用于访问诸如 之类的结构的左值类型,以及诸如不在其中的struct item非字符成员类型。让编译器假定既不也不会别名 aint不需要特殊许可。abstruct item

当然,编译器允许代码获取非字符类型的结构或联合成员的地址,但实际上不允许使用结果指针访问该成员,即使在不这样做的情况下,编译器也是无益的。 t 涉及别名 (*)。然而,该标准没有区分涉及别名的情况和不涉及别名的情况,并且将何时允许使用成员类型左值访问结构的问题完全取决于实现者的判断。gcc 和 clang 的作者可能已经决定,支持在非别名场景中使用指向结构成员的指针的最简单方法是在所有场景中都支持它们,但标准几乎不需要这样的处理,我不认为作者想要它。

该标准为实现提供了从一个假设中受益的空间,即两者都a不会balias c,但仍然支持大多数需要使用指向结构或联合成员的指针的程序。虽然在某些情况下,更多类似的限定符__restrict会有所帮助,但我不确定在您展示的情况下您认为实现需要哪些额外权限。

(*) 即没有操作访问存储区域的情况,或派生将用于这样做的指针/引用,有时存在也将用于访问或寻址相同存储的更新的指针/引用以冲突的方式。


推荐阅读