关于c ++:为什么数组元素长度的地址计算可以被2的幂整除?

Why is address calculation for array element lengths divisible by powers of 2 more efficient?

我正在深入研究指针,因为我认为我对指针没有很好的了解,在维基百科上遇到了以下几点:

When dealing with arrays, the critical lookup operation typically
involves a stage called address calculation which involves
constructing a pointer to the desired data element in the array. If
the data elements in the array have lengths that are divisible by
powers of two, this arithmetic is usually much more efficient.

为什么会这样?

以上行写在标题"用途"下。


乘以2n就是向左移动。现代处理器可以在一个周期内进行移位(在x86中,对于地址计算本身内置的8或16个小移位)。在AMD64机器上,常规的乘法运算需要4-10个时钟周期,而在现代Intel处理器上则很可能类似。对于如何"紧密结合"两个连续的乘法运算也有限制。

当然,如果数组的大小相当大,那么使用乘法指令并将数据压缩得更紧密(不使用填充将数据扩展到2倍大小)可能会更有效,因为缓存效率很高。

当然,现代编译器很聪明,所以如果需要x乘以12,编译器将生成(X << 3) + (X << 2),这比单次乘法运算要快。


第i个元素的地址计算涉及base + size_of_element * i

当元素的大小是2的幂时,假设元素的大小为2^m,那么这可以用base + (i << m)实现。

与前面计算中涉及的乘法相比,移位更有效。


当乘法时,比如在数组中偶然找到第n个成员时,当你处理两个幂的时候,你可以使用移位运算,这比在某些系统上执行完全乘法运算成本最低。


因为偏移量可以用左移位而不是乘法来计算,但是我也会说,考虑到CPU中的流水线数量,这句话可能已经过时了10到20年。