为什么';GCC在将有符号文字指定给无符号类型时是否会产生警告?

为什么';GCC在将有符号文字指定给无符号类型时是否会产生警告?,c,gcc,unsigned,gcc-warning,C,Gcc,Unsigned,Gcc Warning,该网站上的几个问题揭示了混合签名和未签名类型时的陷阱,大多数编译器似乎在生成此类警告方面做得很好。然而,GCC似乎并不在意将有符号常量分配给无符号类型!考虑下面的程序: /* foo.c */ #include <stdio.h> int main(void) { unsigned int x=20, y=-30; if (x > y) { printf("%d > %d\n", x, y); } else { pr

该网站上的几个问题揭示了混合签名和未签名类型时的陷阱,大多数编译器似乎在生成此类警告方面做得很好。然而,GCC似乎并不在意将有符号常量分配给无符号类型!考虑下面的程序:

/* foo.c */
#include <stdio.h>
int main(void)
{
    unsigned int x=20, y=-30;
    if (x > y) {
        printf("%d > %d\n", x, y);
    } else {
        printf("%d <= %d\n", x, y);
    }
    return 0;
}
生成的可执行文件生成以下输出:

$ ./foo
20 <= -30
$。/foo
20使用:


我想这里的问题是,gcc实际上非常擅长生成警告,但默认情况下,对于(有时是意外的)情况,它不会这样做。浏览可用的警告并选择一组选项,生成您认为有帮助的警告,这是一个好主意。或者只是全部,然后润色代码,直到它发光为止!:)

将负值转换为无符号类型的能力是C语言的一个特点。因此,默认情况下不会发出警告。如果你愿意,你必须明确地要求它

至于你的程序输出什么。。。使用
%d
printf的格式说明符
int
和超出类型
int
范围的无符号值会导致未定义的行为,这是您在实验中真正观察到的。使用(无符号)-1是设置所有位的常用方法,有时甚至被引用为C的此(mis)功能的原因,即使是那些应该更清楚的人
. 它既不明显也不可移植——您要用来设置所有位的表达式是~0

请注意,您应该使用%u来打印
无符号int
@Bastien;也许更有趣的是,正如AndreyT在下面的回答中指出的,
printf(“%d”)
显示有符号值,而不是比较运算符使用的无符号值(4294967266)!这是因为符号int的2的补码表示法:(这种表示法不受C标准的保证,但在实践中我从来没有听说过还有另一种表示法在使用)嘿,好主意<代码>printf(“%d”,y)是一个完全不同于
y=-30的类别。很好,例如,我可以想象使用负值来创建所需的位字段。是的-负#到无符号的转换被定义为产生一个结果,该结果与无符号整数的大小“模”成一个数,因此(unsigned)-1是一个非常好的说法,可以表示“一个包含所有1的无符号整数”。当符号数用2的补码表示时,这个“转换”只是与符号相同的位模式。我考虑“UTIN 32×T=1”的含义;显然,该标准指定了精确的行为,它比 UTIN 32×T x=0;[在符号幅度系统上,
~0
窗体将
x
设置为0xFFFF8001ul;在任何16位系统上,
~0u
窗体将
x
设置为0x0000FFFFul;使用
-1
的窗体将在定义
uint32\t
的任何系统上工作]很好,谢谢!希望我有一个<代码> Wallall < /C> >;注意, < WSCONNECT转换> <代码>在C++中<>代码> -WSD/<代码>中默认不启用,因此最好始终显式添加。
$ ./foo
20 <= -30
~/src> gcc -Wconversion -Werror -Wall -Wextra -pedantic -o signwarn signwarn.c
cc1: warnings being treated as errors
signwarn.c: In function 'main':
signwarn.c:5: error: negative integer implicitly converted to unsigned type