答案 0 :(得分:1)
代码,如图所示:
aptr = (aptr + 1) & (void *)(BUFFERSIZE - 1);
// |________| incremented here
由于它是一个循环缓冲区并且缓冲区大小是2的幂,因此&
是一种简单快速的简单掩盖方式。假设BUFFERSIZE
是256
,那么:
num & (256 - 1) == num % 256
num & (0x100 - 1) == num % 0x100
num & (0x0ff) == num % 0x100
如果数字不是2的幂,那么你就不能使用掩蔽技术:
num & (257 - 1) != num % 257
num & (0x101 - 1) != num % 0x101
num & 0x100 != num % 0x101
(void *)
允许编译器根据指针宽度为BUFFERSIZE
常量选择合适的宽度...尽管通常最好知道 - 并使用! - 像这样的陈述之前的宽度。
我添加了十六进制表示法,以便更清楚地说明&
导致模拟翻转事件的原因。请注意0xff
是二进制0x11111111
,因此AND操作只是屏蔽高位。
答案 1 :(得分:1)
这种方法存在两个问题。
A)使用具有逐位操作的指针不是可移植代码。 @Ilja Everilä
char *aptr;
// error: invalid operands to binary & (have 'char *' and 'void *')
// The following increments the index: (not really)
// aptr = (aptr + 1) & (void *)(BUFFERSIZE-1);
B)如果编译器支持void *
类似于char *
的非标准数学运算,如果aptr
指向宽于{{1}的对象,则数学运算错误}和char
是缓冲区中元素的数量,而不是字节大小。当然,这取决于非标准编译器如何实现BUFFERSIZE
。为什么要花费不必要的代码来使用某些特定于实现的行为?
而是使用some_type * & void *
。当i % BUFFERSIZE
是2的幂并且不是{2}时,这种可移植方法有效。当编译器看到BUFFERSIZE
而i % power-of-2
是某些无符号类型时,相同的代码肯定会以i
的形式发出。
对于无法识别此优化的编译器,则应考虑使用更好的编译器。
i & (power-of-2 - 1)