霓虹灯寄存器可以编入索引吗



考虑一个霓虹灯寄存器,例如:

uint16x8_t foo;

要访问单个通道,应该使用vgetq_lane_u16(foo, 3)。然而,考虑到foo是一个空头数组的直觉,人们可能会倾向于编写foo[3]。在这样做的时候,gcc(10(在没有警告的情况下编译,但不清楚它是否做了它想要做的事情

gcc文档没有特别提到索引访问,但它说操作的行为类似于C++valarrays。这些操作确实以直观的方式支持索引访问。

不管foo[3]的评估结果如何,这样做似乎比vgetq_lane_u16(foo, 3)更快,所以它们可能不同,或者我们不需要两者。

那么foo[3]到底是什么意思呢?它的行为有定义吗?如果没有,为什么gcc会愉快地编译它?

foo[3]表单是GCC Vector扩展表单,您已经找到并链接了文档;它的行为是这样的:

向量可以被下标,就好像向量是一个元素数量和基类型相同的数组一样。越界访问在运行时调用未定义的行为。矢量订阅的越界访问警告可以使用-Warray边界启用。

当在big-endian系统上使用时,这可能会产生令人惊讶的结果,因此如果您在同一代码路径中使用vld1等其他Neon内部函数,Arm的Arm C语言扩展建议使用vget_lane