sag*_*agi 23 c unsigned signed gcc compiler-warnings
以下面的C代码为例:
int main(int argc, char *argv[])
{
signed char i;
unsigned char count = 0xFF;
for (i=0; i<count;i++)
{
printf("%x\n", i);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码在无限循环中运行,即使我按如下方式编译它:
# gcc -Wall -Wpedantic -Wconversion -Wsign-compare -Wtype-limits -Wsign-conversion test.c -o test
Run Code Online (Sandbox Code Playgroud)
有人知道应该警告这些问题的编译器标志吗?
为了清楚起见,我不是在问'为什么会得到一个无限循环',而是要知道是否有办法使用编译器或静态分析来阻止它?
250*_*501 13
标志-Wconversion不会捕获错误,因为比较中的两个操作数:i<count,使用整数提升升级到int.
gcc中没有标志可以捕捉到这一点.
除此之外,代码的行为是未定义的,因为变量i溢出,当它具有值0x7F并且递增时:i++.
如果要迭代某个值,请确保您使用的类型可以表示该值.
i是a signed char,将其递增超出SCHAR_MAX具有实现定义的效果.计算i + 1被推广之后进行i到int它不溢出(除非sizeof(int) == 1和SCHAR_MAX == INT_MAX).然而,这个值超出了范围,i并且由于i具有签名类型,结果是实现定义的或者引发实现定义的信号.(C11 6.3.1.3p3有符号和无符号整数).
根据定义,编译器是实现,因此为每个特定系统和x86架构定义行为,其中存储值导致屏蔽低位,gcc应该意识到循环测试肯定是不变的,使其成为无限的环.
请注意,clang它既不会检测常量测试,clang 3.9.0也会检测为if ,如果替换count为const,则会发出警告,不像.i < counti < 0xffgcc
编译器都没有抱怨签名/未签名的比较问题,因为两个操作数实际上都是int在比较之前提升的.
你在这里找到了一个有意义的问题,特别重要,因为一些编码约定坚持对所有变量使用尽可能小的类型,导致像int8_t或uint8_t循环索引变量这样的奇怪.这样的选择确实容易出错,我还没有找到一种方法让编译器警告程序员有关你发布的错误等愚蠢的错误.
| 归档时间: |
|
| 查看次数: |
1397 次 |
| 最近记录: |