c语言里面TMin不能写成-2147483648的原因
2016-07-15 19:15
169 查看
C语言中,将TMin(32位有符号整数的最小值)写成 -2147483647-1,而不是简单地写成 -2147483648 或 0x80000000 。这是为什么呢?
首先,对于整数常量的定义:
可见如果不发生溢出,整型常量的值总是非负数。如果前面出现符号,则是对整型常量使用的一元运算符,而不是整型常量的一部分。整型常量的实际类型取决于长度、基数、后缀字母和C语言实现确定的类型表示精度。具体的根据表一来确定。
其次,看看C语言中limits.h中对于INT_MIN和INT_MAX的定义如下所示:
那么考虑到以上两点,如果将TMin32写成-2147483648并且将代码在一个32位的机器上面编译,当编译器遇到-X形式的数值,它首先会确定X的数据类型和值,然后取X的。
表一 根据C语言版本和常量的格式(十进制和十六进制),常量的数据类型是从上面表格里选择第一个合适(能表示常量)的类型。
表二 根据C语言版本和常量的格式(十进制和十六进制),可以为这两个表达式得到三种不同的数据类型,包括数据为正值的情况。
由于2147483648超过了int所能够表示的范围,编译器就会再次选择一种可以正确的表示此值的类型。然后它就会按照第一个表格(十进制)的顺序往下继续尝试类型,再假设编译器采用的标准是ISO C90,int->long->unsigned,然后就发现unsigned是第一个合适的数据类型。正如我们知道的,2147483648和-2147483648在32位数值上拥有同样的位表示,使得此常量的最终数据类型是unsigned且值为2147483648。这对于16进制的0x80000000也是相同的结果。
对于64位来说十进制和十六进制会分别选择long(-2147483648)和unsigned(2147483648)。而ISO C99的情况则是按照上述规则数据类型为long long才能容纳2147483648。
最后结论是:-214748364832位机器里使用ISO C90进行编译,会先将2147483648看成是一个unsigned,再对2147483648进行无符号的加法逆元计算(见csapp第二版56页),得到结果是:
(-uw2147483648) = 2w - x = 232 - 231 = 231 = 2147483648。
所以对于下面的表达式:
在32位机器里面使用ISO C90进行编译, result = 0。
参考资料:
cs: app web aside
首先,对于整数常量的定义:
An integer constant begins with a digit, but has no period or exponent part. It may have a prefix that specifies its base and a suffix that specifies its type.
可见如果不发生溢出,整型常量的值总是非负数。如果前面出现符号,则是对整型常量使用的一元运算符,而不是整型常量的一部分。整型常量的实际类型取决于长度、基数、后缀字母和C语言实现确定的类型表示精度。具体的根据表一来确定。
其次,看看C语言中limits.h中对于INT_MIN和INT_MAX的定义如下所示:
#define INT_MAX 2147483647 #define INT_MIN (-INT_MAX - 1)
那么考虑到以上两点,如果将TMin32写成-2147483648并且将代码在一个32位的机器上面编译,当编译器遇到-X形式的数值,它首先会确定X的数据类型和值,然后取X的。
ISO C90 | ISO C99 | ||
十进制(Decimal) | 十六进制(Hexadecimal) | 十进制(Decimal) | 十六进制(Hexadecimal) |
int long unsigned unsigned long | int unsigned long unsigned long | int long long long | int unsigned long unsigned long long long unsigned long long |
Wor 4000 d Size | ISO C90 | ISO C99 | ||
Expression | -2147483648 | 0x80000000 | -2147483648 | 0x80000000 |
32 64 | unsigned long | unsigned unsigned | long long long | unsigned unsigned |
由于2147483648超过了int所能够表示的范围,编译器就会再次选择一种可以正确的表示此值的类型。然后它就会按照第一个表格(十进制)的顺序往下继续尝试类型,再假设编译器采用的标准是ISO C90,int->long->unsigned,然后就发现unsigned是第一个合适的数据类型。正如我们知道的,2147483648和-2147483648在32位数值上拥有同样的位表示,使得此常量的最终数据类型是unsigned且值为2147483648。这对于16进制的0x80000000也是相同的结果。
对于64位来说十进制和十六进制会分别选择long(-2147483648)和unsigned(2147483648)。而ISO C99的情况则是按照上述规则数据类型为long long才能容纳2147483648。
最后结论是:-214748364832位机器里使用ISO C90进行编译,会先将2147483648看成是一个unsigned,再对2147483648进行无符号的加法逆元计算(见csapp第二版56页),得到结果是:
(-uw2147483648) = 2w - x = 232 - 231 = 231 = 2147483648。
所以对于下面的表达式:
int result = -2147483648 < 2147483647;
在32位机器里面使用ISO C90进行编译, result = 0。
参考资料:
cs: app web aside
相关文章推荐
- Emacs as a C/C++ Editor/IDE (Part 2)
- C语言 操作符和表达式
- Cpp环境【POJ 2375】【Vijos1642】雪场缆车
- Linked List Cycle
- 《30天自制操作系统》 day0-day2小结
- July 15th 模拟赛C T3 最小最大和 Solution
- 洛谷 P1079 [NOIP2012 D1T1] Vigenère 密码
- if选择结构
- C++ 通过ADO.Net实现与MySql数据库连接 入门教程
- July 15th 模拟赛C T2 积木游戏 Solution
- 常见排序算法C/C++实现总结
- C++实现RTMP协议发送H.264编码及AAC编码的音视频
- c++动态链接
- 洛谷 P1330 封锁阳光大学
- Observer观察者模式
- C++ 队列queue的用法
- C++ bitmap
- c++构造和析构能不能抛异常的问题!
- 树(1)把二叉查找树转换成有序的双向链表
- c语言--内部名外部名