探究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类型的,这个小技巧使得我们获得了正确的类型和正确的值。

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

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


目录
相关文章
|
27天前
|
存储 算法 程序员
C语言:库函数
C语言的库函数是预定义的函数,用于执行常见的编程任务,如输入输出、字符串处理、数学运算等。使用库函数可以简化编程工作,提高开发效率。C标准库提供了丰富的函数,满足各种需求。
|
1月前
|
存储 编译器 C语言
C语言函数的定义与函数的声明的区别
C语言中,函数的定义包含函数的实现,即具体执行的代码块;而函数的声明仅描述函数的名称、返回类型和参数列表,用于告知编译器函数的存在,但不包含实现细节。声明通常放在头文件中,定义则在源文件中。
ly~
|
1月前
|
数据可视化 BI API
除了 OpenGL,还有哪些常用的图形库可以在 C 语言中使用?
除了OpenGL,C语言中还有多个常用的图形库:SDL,适合初学者,用于2D游戏和多媒体应用;Allegro,高性能,支持2D/3D图形,广泛应用于游戏开发;Cairo,矢量图形库,支持高质量图形输出,适用于数据可视化;SFML,提供简单接口,用于2D/3D游戏及多媒体应用;GTK+,开源窗口工具包,用于创建图形用户界面。这些库各有特色,适用于不同的开发需求。
ly~
228 4
|
1月前
|
存储 安全 编译器
深入C语言库:字符与字符串函数模拟实现
深入C语言库:字符与字符串函数模拟实现
|
2月前
|
安全 编译器 C语言
C语言常量的定义与使用的注意点
在 C 语言中,常量是在程序运行期间值不变的量,通过字面值、`#define` 或 `const` 关键字定义。字面常量直接在代码中表示固定值,如整数 `100`、浮点数 `3.14`、字符 `&#39;A&#39;` 和字符串 `&quot;Hello, World!&quot;`;`#define` 用于定义宏,如 `#define PI 3.14159`;`const` 则定义不可变变量,如 `const int daysInWeek = 7`。常量可用于数组大小、循环边界等场景,并能提升代码的可读性和可维护性。使用时需注意作用域、类型安全和命名,避免直接使用数字(魔法数字)。
|
2月前
|
存储 算法 C语言
数据结构基础详解(C语言):单链表_定义_初始化_插入_删除_查找_建立操作_纯c语言代码注释讲解
本文详细介绍了单链表的理论知识,涵盖单链表的定义、优点与缺点,并通过示例代码讲解了单链表的初始化、插入、删除、查找等核心操作。文中还具体分析了按位序插入、指定节点前后插入、按位序删除及按值查找等算法实现,并提供了尾插法和头插法建立单链表的方法,帮助读者深入理解单链表的基本原理与应用技巧。
560 6
|
3月前
|
搜索推荐 算法 Java
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
该博客文章通过UML类图和Java源码示例,展示了如何使用适配器模式将QuickSort类和BinarySearch类的排序和查找功能适配到DataOperation接口中,实现算法的解耦和复用。
42 1
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
|
3月前
|
C语言
C语言中的math库概述
C语言中的math库概述
108 1
|
3月前
|
编译器 程序员 C语言
C语言 宏
C语言 宏
40 5
|
3月前
|
存储 Serverless C语言
C语言中的标准库函数
C语言中的标准库函数
55 0