void main() {
unsigned int a = 0;
if (a - 10 < 0) {
printf("error!\n");
}
}
我们知道这种比较是行不通的,因为-10是一个大的无符号整数,它不能小于0。
为了避免这种情况,我这样尝试:
void main() {
unsigned int a = 0;
int b = 0;// or const int b = 0;
if (a - 10 < b) {
printf("error!\n");
}
}
这将使用Visual Studio 2022 17.2.4获得warning C4018
。
但是,当我使用gcc 4.8.5时,根本没有任何警告。
有没有一种方法可以避免编码器将有符号数与无符号变量进行比较?
更新:更复杂的情况可能是:
struct s{
unsigned int len;
char *buffer;
} *a;
int not_safe(struct s *ptr){
if(ptr->len - sizeof(struct s) < 0){
return 0;
}
return 1;
}
程序员可能没有意识到这样的比较是错误的。我希望我们能有一个安全的方法让程序员避免这种情况。
2条答案
按热度按时间jgzswidk1#
如果将
unsigned int
操作数转换为int
:然后使用类型
int
完成所有的数学运算。或者,你可以做一点代数:
完全避开了这个问题。
0aydgbwb2#
请学习一下C正式调用的 * 通常的算术转换 * Implicit type promotion rules.tl; DR的意思是,如果你有两个大小相同但符号不同的整数,有符号的整数会被转换成无符号的整数。
您可以将无符号操作数显式转换为有符号操作数。或者,您可以让有符号操作数的类型大于无符号操作数的类型,例如
int64_t
,在这种情况下,unsigned int
(可能是16位或32位)将转换为int64_t
。但这并不能解决你的根本问题,那就是这一行:
这从一开始就没有任何意义。并且将
ptr->len
转换为int64_t
可能没有帮助,或者sizesizeof
返回一个size_t
,它肯定是一个大的无符号整数类型。只需将其替换为:或者,如果您愿意,请将整个函数更改为以下常用最佳做法之一: