当前位置:  开发笔记 > 大数据 > 正文

为什么最小的int,-2147483648,类型为'long'?

如何解决《为什么最小的int,-2147483648,类型为'long'?》经验,为你挑选了2个好方法。

对于学校项目,我要编写C函数printf.事情进展顺利,但有一个问题我找不到合适的答案,所以我在这里.

printf("PRINTF(d) \t: %d\n", -2147483648);

告诉我(gcc -Werror -Wextra -Wall):

   error: format specifies type 'int' but the argument has type 'long'
      [-Werror,-Wformat]
        printf("PRINTF(d) \t: %d\n", -2147483648);
                              ~~     ^~~~~~~~~~~
                              %ld

但是如果我使用int变量,一切都很顺利:

int i;

i = -2147483648;
printf("%d", i);

为什么?

编辑:

我理解了许多观点,他们非常有趣.无论如何,我猜printf是使用librairy,所以,va_arg(va_list ap, type)也应该返回正确的类型.对于%d%i,显然返回的类型是int.它有什么改变吗?



1> fuz..:

在C中,-2147483648不是整数常量.2147483648是一个整数常量,-只是一个应用于它的一元运算符,产生一个常量表达式.值2147483648不适合int(它太大,2147483647通常是最大的整数),因此整数常量具有类型long,这会导致您观察到的问题.如果你想提一个下限int,无论是使用宏INT_MIN(便携式办法)或小心避免提及2147483648:

printf("PRINTF(d) \t: %d\n", -1 - 2147483647);



2> rici..:

问题是它-2147483648不是整数文字.它是由一元否定操作者的表达-和整数2147483648,这是太大,是一个int如果ints为32位.由于编译器2147483648在应用否定运算符之前将选择适当大小的有符号整数来表示,因此结果的类型将大于a int.

如果您知道您的ints是32位,并且想要在不破坏可读性的情况下避免警告,请使用显式强制转换:

printf("PRINTF(d) \t: %d\n", (int)(-2147483648));

这是在具有32位ints 的2的补码机器上定义的行为.

为了提高理论上的可移植性,请使用INT_MIN而不是使用数字,并告诉我们您在哪里找到非二进制补码机器进行测试.


要明确的是,最后一段部分是一个笑话.INT_MIN如果你的意思是"最小的int",那绝对是你要走的路,因为int它的大小各不相同.例如,仍有许多16位实现.写出-2 31只有在你总是精确地指那个值时才有用,在这种情况下你可能会使用固定大小的类型int32_t而不是int.

你可能会想一些替代十进制写出的数量,使之更清晰对于那些谁可能没有注意到的区别21474836482174483648,但你必须要小心.

如上所述,在32位二进制补码机器上,(int)(-2147483648)不会溢出,因此定义明确,因为-2147483648它将作为更宽的有符号类型进行处理.但是,情况并非如此(int)(-0x80000000).0x80000000将被视为一个unsigned int(因为它适合无符号表示); -0x80000000被良好定义(但-如果没有效果int是32位),并且将所得的转化unsigned int 0x80000000int涉及溢出.为避免溢出,您需要将十六进制常量转换为带符号的类型:(int)(-(long long)(0x80000000)).

同样,如果要使用左移位运算符,则需要注意.1<<31在具有32位(或更小)ints的32位计算机上是未定义的行为; 如果至少是33位,则它将仅评估为2 31int,因为k如果k严格地小于左侧参数的整数类型的非符号位的数量,则仅按比特左移定义.

1LL<<31是安全的,因为long long int要求能够代表2 63 -1,所以它的位大小必须大于32.所以形式

(int)(-(1LL<<31))

可能是最具可读性的.因人而异.


对于任何通过悬挂物,这个问题被标记C,以及最新的C草案(n1570.pdf)说,相对于E1 << E2,其中E1有一个符号类型,该值仅被定义,如果E1是负,并且"是结果型的可表示".(§6.5.7第4段).E1 × 2E2

这与C++不同,在C++中定义了左移运算符的应用,如果E1它是非负的并且"可以结果类型的相应无符号类型中表示 "(§5.8第2段,强调添加).E1 × 2E2

在C++中,根据最新的草案标准,如果值无法在目标类型中表示,则将整数值转换为有符号整数类型是实现定义的(第4.7节第3段).C标准的相应段落 - §6.3.1.3段.3 - 表示"结果是实现定义的或者实现定义的信号被引发".)


来定义传统的方式`INT_MIN`是`的#define INT_MIN( - (INT_MAX)-1).`,(这避免试图需要很长的,你所描述的负的问题[*(参考)*](HTTP ://www.hardtoc.com/archives/119)
@abelenky:我知道在2s补充机器*上传统上定义了`INT_MIN`*.否则,我认为将它定义为`( - INT_MAX)`是有意义的,因为仅键入数字2147483647是有意义的.但是(合理地)建议用`-2147483647-1`调用printf有点奇怪.当然,既然我们已经进行了这次讨论,我们知道你为什么要这样做.我只建议使用显式强制转换让你以通常由既不编译也不是语言律师的人写的形式写出文字数:)
推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有