C无符号模数会导致编译器警告

前端之家收集整理的这篇文章主要介绍了C无符号模数会导致编译器警告前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在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比前部元素的实际索引小1(当然,以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)的行,抱怨:

Warning : C2705: Possible loss of data

main.c line 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];

但是,我的编译器仍会发出相同的警告,这次是关于行(B).也许编译器告诉我在语句中(tfront 1> = tsize),tfront在执行之前可能是255,并且溢出.当然,我知道这不会发生,但我的编译器却没有.

如果是这种情况,为什么线(A)成为问题?基本上,我想知道编译器不满意的是什么.

键入我的问题后,我通过将tsize从变量类型更改为预处理器定义(即#define TSIZE 16)来解决它.不过,我的问题仍然存在.

一些相关问题:
unsigned overflow with modulus operator in C
modulus operator with unsigned chars

解决方法

编译器警告可能来自tfront%= tsize;这相当于tfront = tfront%tsize;这一事实,因为C中的提升规则表达式tfront%tsize具有(*)类型int.

如果你写tfront =(byte)(tfront%tsize),它可能会使编译器静音;代替.

没有特别的理由担心,你的编译器确实会发出奇怪的警告:尽管表达式tfront%tsize在技术上具有int类型,但由于计算方式,它的值都适合于一个字节.即使这些值并非都适合一个字节,但无符号整数类型的C标准保证了环绕行为(因此,您有理由使用此环绕行为).

(*)除非在你的编译平台上int不能包含unsigned char可以采用的所有值,在这种情况下它将是unsigned int类型,你可能不会看到警告.

猜你在找的C&C++相关文章