如何指示结构成员没有锯齿?
How to indicate absence of aliasing for a struct member?
如果你写这样的语句:
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].foo
和c[i].bar
。在这种情况下,如何针对结构的各个字段声明关于指针独立的等效断言?
目前,我已经设法使用以下方法解决了这个问题:
#pragma GCC ivdep
但是,这会完全关闭依赖项检查。我仍然对更具选择性的解决方案感兴趣。
该标准不要求编译器适应a[anything]
和b[anything]
可用于访问struct item
的任何部分的可能性。 它列出了实现必须始终允许用于访问结构(如struct item
(的左值类型,而非字符成员类型(如int
(不在其中。 不需要特殊权限即可让编译器假设a
和b
都不会为struct item
别名。
当然,编译器允许代码采用非字符类型的结构或联合成员的地址,但实际上从未允许使用生成的指针访问成员,即使在不涉及 aliasing(*( 的情况下,编译器也是相当无益的。 然而,该标准没有区分涉及别名的情况和不涉及别名的情况,并且将何时允许使用成员类型标签值访问结构的问题完全取决于实现者的判断。 gcc 和 clang 的作者可能已经决定,在非锯齿场景中支持使用指针来结构成员的最简单方法是在所有场景中支持它们,但标准几乎不需要这样的处理,我认为作者不希望这样做。
该标准为实现提供了空间,可以从以下假设中受益:a
不b
都不会别名c
,但仍然支持大多数需要使用指向结构或工会成员的指针的程序。 虽然在某些情况下,更多类似于__restrict
的限定符会有所帮助,但我不确定您认为在您展示的情况中实现需要什么额外的权限。
(*( 即没有操作访问存储区域的情况,或者派生将用于执行此操作的指针/引用,有时存在较新的指针/引用,该指针/引用也将用于以冲突的方式访问或寻址同一存储。
没有必要这样做。
要么编译器足够聪明,知道这些结构成员不能别名,要么不够聪明,无法对这些信息做任何有用的事情。
__restrict__
和 C99restrict
关键字的原因是,与结构不同,数组可能会别名。因此,关键字为编译器提供了真实而有用的信息。
- 如何在C++中定义静态成员结构
- 使用模板化类的成员结构
- 初始化固定的 C 数组成员结构
- 指向成员结构的指针如何工作
- 如何将此“指针从外部类传递到成员结构
- 导致IAR ARM中出现错误的成员结构位字段元素的Initializer列表初始化
- 映射文件中成员结构的地址
- Visual C++ 模板类成员结构初始化语法糖
- C :初始化成员结构的静态字段的正确方法
- 如何在C 类的初始化器列表中使用未命名结构初始化成员结构
- 从成员结构的成员函数中访问类的成员?
- 模板化类的成员函数无法返回指向成员结构的指针?
- 重载非类型模板结构的成员结构的复制赋值运算符
- 灵气属性传播问题与单成员结构.
- 将具有 int* 成员C++结构编接到 C#
- 复杂的班级成员结构
- 将向量成员(结构)传递给函数
- 成员结构的前向声明
- 重载运算符<<用于模板结构中定义的成员结构
- 返回带有模板化类的类成员结构