使用备用方法增加循环缓冲区

时间:2017-10-17 16:27:24

标签: c

Circular buffer incrementation 我无法理解最后一个语句如何增加指针。有人用几个例子解释我吗?

2 个答案:

答案 0 :(得分:1)

代码,如图所示:

aptr = (aptr + 1) & (void *)(BUFFERSIZE - 1);
    // |________| incremented here

由于它是一个循环缓冲区并且缓冲区大小是2的幂,因此&是一种简单快速的简单掩盖方式。假设BUFFERSIZE256,那么:

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}时,这种可移植方法有效。当编译器看到BUFFERSIZEi % power-of-2是某些无符号类型时,相同的代码肯定会以i的形式发出。

对于无法识别此优化的编译器,则应考虑使用更好的编译器。

i & (power-of-2 - 1)