考虑一个霓虹灯寄存器,例如:
uint16x8_t foo;
要访问单个通道,应该使用vgetq_lane_u16(foo, 3)
。然而,考虑到foo
是一个空头数组的直觉,人们可能会倾向于编写foo[3]
。在这样做的时候,gcc(10(在没有警告的情况下编译,但不清楚它是否做了它想要做的事情
gcc文档没有特别提到索引访问,但它说操作的行为类似于C++valarray
s。这些操作确实以直观的方式支持索引访问。
不管foo[3]
的评估结果如何,这样做似乎比vgetq_lane_u16(foo, 3)
更快,所以它们可能不同,或者我们不需要两者。
那么foo[3]
到底是什么意思呢?它的行为有定义吗?如果没有,为什么gcc会愉快地编译它?
foo[3]
表单是GCC Vector扩展表单,您已经找到并链接了文档;它的行为是这样的:
向量可以被下标,就好像向量是一个元素数量和基类型相同的数组一样。越界访问在运行时调用未定义的行为。矢量订阅的越界访问警告可以使用-Warray边界启用。
当在big-endian系统上使用时,这可能会产生令人惊讶的结果,因此如果您在同一代码路径中使用vld1
等其他Neon内部函数,Arm的Arm C语言扩展建议使用vget_lane
。