探究C语言标准库limits.h关于INT_MIN宏的奇怪定义

简介:

最近在读《深入理解计算机系统》(顺便打个广告,卡内基梅隆出品的这本书绝对精品),在书的48页提到了在C语言标准库limits.h中将int类型的最小值INT_MIN定义为-INT_MAX-1。书中提到了为何不写做-2147483648或者0x80000000,但是并没有给出解释,只是说这需要我们钻研C语言标准的一些比较隐晦的角落。

我们先看看MSVC的相关头文件内容:

GCC也给出了类似的定义方式:

为何是这样呢?这个头文件对我来说并不陌生。这几个宏也时常在用着,但是从没有注意过这个细节问题。百度一番后没找到满意的答案,最后勉强找到了http://www.hardtoc.com/archives/119这个比较靠谱的答案。因为英文看起来比较麻烦,再者作者描述的也不是很清楚,我写篇文章 权当翻译 一下,再加上一点点自己查到的内容。

我们先来查看C语言标准文档是怎么解释常量的,ISO/ANSI C99 和C11对于这里的描述是相同的。我们摘录下来:

“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.”

大概意思是“一个常量起始于一个数字,但是不包含小数点或指数的部分。并且可能有一个用于指定数字基底的前缀和一个指定类型的后缀。”

这里的前缀比如16进制的0x,后缀比如指明是长整型的L或者无符号的U。

简而言之,c99对整数的定义是这样的:


D                        [0-9]
IS                       (u|U|l|L)*
{D}+{IS}?
 

不知道大家有没有注意到,这里没有提到正负号,或而言之,常量不包含符号。

下一段引用自 幻の上帝:

C语言中的常量(constant)和常量表达式(constant expression)是两个概念。前者是语法规定的一些记号(token);后者语法本质是条件表达式(conditional-expression),只是加了能在翻译而不是运行时求值的语义限制。 C语言中的常量(constant)和常量表达式(constant expression)是两个概念。前者是语法规定的一些记号(token);后者语法本质是条件表达式(conditional-expression),只是加了能在翻译而不是运行时求值的语义限制。

那么,我们假设INT_MIN定义为-2147483648,这里的-2147483648其实是由一个一元运算符-和一个常量2147483648组成,编译器怎么解释2147483648呢?编译器对于这么一个数字,按照定义好的变量顺序一一匹配其类型,这个定义好的顺序在文档里可以查到,C99和C11是一样的,另外C++11也是相同的。截图如下:

首先是由int开始,因为2147483648超过了int的最大取值范围2147483647,所以会被认为是long int类型。按照C语言的表达式求值规则,原本可能使用的x < INT_MIN这样的表达式,x被转换为long int类型再进行表达式求值了,便有可能会出现一些预料之外的结果,而按照-2147483647-1这样的定义,不会被认为是long int类型的,这个小技巧使得我们获得了正确的类型和正确的值。

这样解释不知道大家明白了没有?

这篇文章基本上是查证和翻译了,如果说有版权的话,原始版权归原作者所有。


目录
相关文章
|
9天前
|
程序员 C语言
C语言库函数 — 内存函数(含模拟实现内存函数)
C语言库函数 — 内存函数(含模拟实现内存函数)
18 0
|
29天前
|
安全 程序员 C语言
探索C语言库函数:字符串拷贝函数strcpy
探索C语言库函数:字符串拷贝函数strcpy
19 0
|
1月前
|
SQL 流计算 OceanBase
OceanBase CDC从热OB库采集过来的Tinyint(1)类型会默认转换成Boolean,请教一下,如果想转换成int类型,有什方法么?
【2月更文挑战第25天】OceanBase CDC从热OB库采集过来的Tinyint(1)类型会默认转换成Boolean,请教一下,如果想转换成int类型,有什方法么?
27 3
|
1月前
|
C语言
模拟实现C语言中经典库函数,字符相关的函数与内存相关的函数
模拟实现C语言中经典库函数,字符相关的函数与内存相关的函数
模拟实现C语言中经典库函数,字符相关的函数与内存相关的函数
|
1月前
|
存储 安全 C语言
C语言抽象数据类型栈的定义讲解
C语言抽象数据类型栈的定义讲解
19 0
C4.
|
1月前
|
存储 程序员 数据处理
C语言怎样定义和引用一维数组
C语言怎样定义和引用一维数组
C4.
13 0
|
12天前
|
存储 编译器 Linux
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
C4.
|
1月前
|
存储 C语言
C语言怎样定义和引用二维数组
C语言怎样定义和引用二维数组
C4.
14 0
|
1月前
|
存储 C语言
C语言栈的表示和实现的定义讲解
C语言栈的表示和实现的定义讲解
20 0
|
1月前
|
编译器 C语言
C语言宏定义(#define定义常量​、#define定义宏​、 带有副作用的宏参数、 宏替换的规则、 宏函数的对比)
C语言宏定义(#define定义常量​、#define定义宏​、 带有副作用的宏参数、 宏替换的规则、 宏函数的对比)

热门文章

最新文章