gcc 如何避免无符号整数与有符号数比较?

hc2pp10m  于 2022-11-30  发布在  其他
关注(0)|答案(2)|浏览(135)
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;
}

程序员可能没有意识到这样的比较是错误的。我希望我们能有一个安全的方法让程序员避免这种情况。

jgzswidk

jgzswidk1#

如果将unsigned int操作数转换为int

if ((int)a - 10 < 0)

然后使用类型int完成所有的数学运算。
或者,你可以做一点代数:

if (a < 10)

完全避开了这个问题。

0aydgbwb

0aydgbwb2#

请学习一下C正式调用的 * 通常的算术转换 * Implicit type promotion rules.tl; DR的意思是,如果你有两个大小相同但符号不同的整数,有符号的整数会被转换成无符号的整数。
您可以将无符号操作数显式转换为有符号操作数。或者,您可以让有符号操作数的类型大于无符号操作数的类型,例如int64_t,在这种情况下,unsigned int(可能是16位或32位)将转换为int64_t
但这并不能解决你的根本问题,那就是这一行:

if(ptr->len - sizeof(struct s) < 0)

这从一开始就没有任何意义。并且将ptr->len转换为int64_t可能没有帮助,或者size sizeof返回一个size_t,它肯定是一个大的无符号整数类型。只需将其替换为:

if(sizeof(struct s) > ptr->len)

或者,如果您愿意,请将整个函数更改为以下常用最佳做法之一:

bool not_safe (const struct s* ptr) {
  return sizeof(struct s) > ptr->len;
}

相关问题