在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在看《深入理解计算机系统》第二版中文版时(Computer Systems A Programmer's Perspective Second Edititon),看到48页第二章网络旁注中提到: 在这篇博文的写作过程中,搜到了一些很有用的资料,请见本文末尾的参考资料一节。本文中很大部分内容都是参照 CS:APP Web Aside DATA:TMIN: C语言中整型常量的实际类型首先来看一下C语言中整型常量的定义。 C99标准中 6.4.4.1 Integer constants 中提到: 可见如果不发生溢出,整型常量的值总是非负数。如果前面出现符号,则是对整型常量使用的一元运算符,而不是整型常量的一部分。 整型常量的实际类型取决于长度、基数、后缀字母和C语言实现确定的类型表示精度。确定整数常量类型的规则比较复杂,并且在非标准C、C89和C99中是不相同的。具体规则可见<<C语言参考手册》第五版 第二章 2.7.1 整型常量一节。对于本文中提到的场景,下面的这个整数常量的类型表就够用了。 表一:整数常量的类型
根据C语言版本和常量的格式(十进制和十六进制),常量的数据类型是从上面表格里选择第一个最合适(能表示常量而不溢出的)的类型。 对于ISO C90,编译器依次尝试int 、long、 unsigned(32位机器上long跟int一样,是32位), 最终选择unsigned来表示。对于 2147483648 和 -2147483648,如果表示为32位的二进制数字,它们的位表示是一样的,都是0x80000000。所以这个常量表达式(-2147483648)的数据类型为unsigned且值为 2147483648。 对于ISO C99,编译器依次选择 int、long、long long,最终选择long long类型才能容纳 2147483648 。用64位,可以唯一表示 2147483648 和 -2147483648,所以这个常量表达式的数据类型为long long,值为 -2147483648。 对于16进制常数 0x80000000(注意,按照C语言中整型常量的定义,这个整数常量是正数,值为2417483648),在32位机器上,编译器也是利用同样的规则,依照表一中的16进制的列表来处理。两个语言标准中,都是首先跟TMax32(0x7FFFFFFF)比较,由于0x80000000更大,所以这个值不能用int来表示。接下来和UMax32(0xFFFFFFFF)比较,由于比它小一些,所以选择unsigned来表示。所以这个常量表达式的数据类型是unsigned,值为0x80000000(或者说,是等于2147483648)。 在64位的机器上,事情稍微有些不同。两个语言标准中,十进制的格式 -2417483648 都是long(64位)类型,值为 -2417483648,然而十六进制格式 0x80000000 都是unsigned类型,值为0x80000000(或者说,是 2147483648)。 用一句话来解释C语言中TMin32的古怪写法的原因:虽然-2147483648 这个数值能够用 C语言中如何正确表示TMin32呢?C语言中limits.h中定义了如下两个宏: #define INT_MAX 2147483647 #define INT_MIN (-INT_MAX - 1) ISO C99在stdint.h文件中定义了一些宏 INTN_C、UINTN_C、INTMAX_C与UINTMAX_C,提供对整型常量的长度与类型的可移植性控制。 知道这个有什么用?:1. 考虑如下代码: int dcomp = (-2147483648 < 0); int hcomp = (0x80000000 < 0); 请大家思考一下dcomp和hcomp的值是0还是1?需要考虑编译器指定的C语言版本和机器位数(字的大小)。 gcc 中,C模式默认的C语言标准是gnu89(ISO C90, 包括一些C99特性)。可以通过 -std 选项来指定C语言的版本。 MSVC支持C90,只支持部分的C99特性。 2. 考虑如下代码: int dtmin = -2147483648; int dcomp2 = (dtmin < 0); int htmin = 0x80000000; int hcomp2 = (htmin < 0); 如果你亲自在32位和64位机器上用ISO-C90和ISO-C99版本来编译运行一下,会发现,所有情况下,dcomp2和hcomp2的值都是1。你能解释一下为什么吗?
广告一下吧,在搜 TMin 资料的时候,发现了一本书《一站式学习C编程》,网上有第一版的html的版本,我只看了其中介绍整型 的一节,发现作者写的通俗易懂,而且是国人写的,必须得支持啊。 参考资料: C语言参考手册第五版 2.7.1 整型常量 补充阅读: 由于补码的不对称性,导致在用补码来表示负数的编译器中使用abs()函数会有问题
如果您看了本篇博客,觉得对您有所收获,请点击右下角的“推荐”,让更多人看到! 资助Jack47写作,打赏一个鸡蛋灌饼钱吧
微信打赏
支付宝打赏
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论