GCC在将==op与有符号变量和无符号文字一起使用时不会发出警告

GCC在将==op与有符号变量和无符号文字一起使用时不会发出警告,gcc,casting,compiler-warnings,Gcc,Casting,Compiler Warnings,为什么GCC只针对下面代码中的情况1和3而不是2发出警告 我正在使用-Wall和-g标志编译 int main() { unsigned int ui = 4; int si = 6; if (si == ui ) { // Warning comparison b/w signed and unsigned printf("xxxx"); } if (si == 2U ) { // No Warning --- WHY ???

为什么GCC只针对下面代码中的情况1和3而不是2发出警告

我正在使用-Wall和-g标志编译

int main() {

    unsigned int ui = 4;
    int si = 6;

    if (si == ui ) { // Warning comparison b/w signed and unsigned
        printf("xxxx");
    }

    if (si == 2U ) { // No Warning --- WHY ???
        printf("xxxx");
    }

    if (si > 2U ) { // Warning comparison b/w signed and unsigned
        printf("xxxx");
    }

    return 0;
}
:

-Wconversion部分:

不要对显式强制转换发出警告,如
abs((int)x)
ui=(未签名)
-1
,或者如果该值未通过类似于
abs(2.0)
中的转换进行更改

由于
2U
是文字,gcc知道:

  • 如果
    si<0
    ,则
    (无符号)si>=2^31
    ,因此
    s1!=2U
  • 如果
    si>0
    ,则
    (无符号)si
    si
    具有相同的值,因此
    (无符号)si==2U
    当且仅当
    si==2
总之,将有符号的
si
与文字的
2U
进行比较与将
si
2
进行比较是一样的,即将
si==2U
转换为
unsigned
不会改变结果


如果与2^32-1(4294967295U)进行比较,
int
中无法表示的最大32位无符号int,那么
si
可能等于它,即使
si
本身为负数,这可能不是您想要的,因此,使用
-Wextra
选项生成警告。

可能是因为在类型的有符号和无符号版本重叠的范围内,与常量进行相等比较时没有歧义

如果我把它改成


如果(si==2147483648U){
printf(“xxxx”);
}

我得到一个警告


(事实上,在收到您报告的警告之前,我不得不添加-Wextra)

克里斯谢谢您的回答。我认为这是原因所在。我最初的想法是,U后缀将导致此文本升级为无符号类型,但我认为只有当数字大于INT_MAX_32,即大于2147483647时,才会将其升级为无符号类型

它确实“升级”为无符号,但当它的值小于2^31-1时没有区别。@ryanli:如果它总是升级为无符号,那么si==2U也应该抛出警告。为什么2147483647是一个神奇的点,只有一面墙的旗帜,gcc应该开始发出警告。我想我不明白你最初的答案。因为
2U
是一个文字,尽管
si
签名的
,gcc在编译时清楚地知道,
si
可以与
2U
的值进行比较,而不会丢失准确性:如果
si
本身为负数,则升级为unsigned后不等于
2U
。但对于大于2^31-1的文字值,gcc会抛出警告,因为如果
si
为负,则
si
可能等于文字,这可能不是您期望的结果。而且,
-Wall
并没有像我回答中的链接所显示的那样发出任何警告。@ryanli:谢谢,现在有道理了。