我有以下数组,我打算将其用作循环缓冲区。
int array1[20];
该数组由一个线程写入并由另一个线程读取。在阅读时,我需要阅读该数组中写入的最后 3 个值。
写作效果很好。我用
writeIndex = (writeIndex + 1) %20;
来写。这很好地将数组索引 0 翻转到 19。
为了阅读我正在使用
readIndex = (readIndex -1)%20;
但是当我尝试从索引 0 到 19 时它不起作用。
你的代码
readIndex = (readIndex - 1) % 20;
不起作用,因为当readIndex
以 0 开头时,(readIndex - 1) % 20
将评估为 -1,然后您的数组访问将超出范围。
在这种情况下,您不想处理负数。为避免这种情况发生,您只需将 20 添加到该值:
readIndex = (readIndex - 1 + 20) % 20;
或者干脆
readIndex = (readIndex + 19) % 20;
所以当readIndex
从 0 开始时,你可以回绕到 19。
李玉修给出了实际的答案,这里有一些背景信息。
问题是在 C 中定义除法/模数的方式:除法向零舍入,模数定义为
a%b == a - (a/b)*b
由于除法四舍五入为零,-1/20
因此为零。因此,-1%20 == -1 - 0*20
yield-1
不是数组的有效索引。
好的,抛开线程,这是一个测试程序,可以满足您的需求。但是您可能想要添加一些内容以确保您至少有 3 个读数(我没有为此烦恼)。但重要的计算是获取当前位置 (bufferPos),并找到 3 (N) 个先前的值。
哦,在我评论锁定和解锁的地方,把你的线程锁定......
#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE (20)
int bufferPos = 0;
int Databuffer[BUFSIZE] = {0};
int BufferWrite(int x)
{
//lock
Databuffer[bufferPos] = x;
bufferPos = (bufferPos+1)%BUFSIZE;
printf("write[%d] %d\n", bufferPos, Databuffer[bufferPos]);
//unlock
}
int BufferRead(int count)
{
int rdx;
int position;
//lock
for( rdx=0; rdx<count; ++rdx )
{
position = ((bufferPos-1)-rdx);
if( position<0 ) position = position+BUFSIZE;
printf("read[%d:%d] %d\n", rdx, position, Databuffer[position]);
}
//unlock
}
int main(int argc, char* argv[])
{
int ndx; int val;
char line[999];
for( ndx=0; ndx<100; ++ndx )
{
fgets(line,sizeof(line),stdin);
BufferWrite(atoi(line));
if( ndx%7 == 0 ) //read a few, occasionally
{
BufferRead(3);
}
}
}