在 MC9S12C32 微控制器的一些嵌入式 C 代码中,我有一个循环队列(又名循环缓冲区),它用一个静态大小的字节数组和队列前后的两个“指针”实现,这实际上只是队列的索引大批。
// call unsigned chars bytes
typedef unsigned char byte;
byte trear = 0; // SCI transmit display buffer IN index
byte tfront = 0; // SCI transmit display buffer OUT index
byte tsize = 16; // size of transmit buffer
byte tbuf[16]= {0};// SCI transmit display buffer
请注意,这trear
是后元素的实际索引,但tfront
比前元素的实际索引小一(当然以模 16 为准)。因此,例如,如果我的缓冲区包含“hello”,它可能看起来像这样(其中空槽是垃圾值):
_________________________________
| | |h|e|l|l|o| | | | | | | | | |
^ ^
front rear
当需要从队列中删除一个字节时,我会这样做:
// increment front index
tfront++;
// wrap front index if it exceeded bounds
tfront %= tsize; // (A)
// get character to transmit
byte outputChar = tbuf[tfront];
这一切都很好——至少,我的程序没有出现与这个片段相关的错误。然而,当我编译这个程序时,我的编译器警告我(A)
上面片段中标记的行,抱怨:
警告:C2705:可能丢失数据
main.c 第 402 行
第 402 行是 (A) 行。我应该注意我没有使用 gcc 或类似的东西;我在飞思卡尔的 CodeWarrior IDE 中进行编译,它有时会给我其他一些有点神秘的警告。为了摆脱警告,我将上面的片段重写为:
// increment front index mod tsize
tfront = (tfront + 1 >= tsize) ? 0 : tfront + 1; // (B)
// get character to transmit
byte outputChar = tbuf[tfront];
但是,我的编译器仍然发出相同的警告,这次是关于 line (B)
。也许编译器告诉我,在语句中(tfront + 1 >= tsize)
,tfront
执行前可能是 255,并且溢出。当然,我知道这不会发生,但我的编译器不会。
但是,如果是这种情况,为什么线路(A)
是一个问题?基本上,我想知道编译器对什么不满意。
自从输入我的问题后,我通过将tsize
变量类型更改为预处理器定义(即#define TSIZE 16
)来解决它。不过,我的问题仍然存在。
一些相关问题:
C 模运算符中的无符号溢出与模运算
符与无符号字符