c语言 头文件可以定义的函数吗_C 语言 <limits.h> 头文件中 INT_MIN 奇怪定义的分析...

C 语言标准库中定义了整型数的最大值和最小值,以 GCC 编译器为例,其定义如下:

#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX-1)

这里产生一个疑问:为什么INT_MIN不直接定义成 -2147483648,而是写成 -2147483647-1 这种形式呢?

这里涉及到 C 语言如何定义常量,C 语言标准文档对常量的解释如下:“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.”

大概意思是“一个常量起始于一个数字,但是不包含小数点或指数的部分。并且可能有一个用于指定数字基底的前缀和一个指定类型的后缀。”这里的前缀比如0xFF中的0x,后缀比如100UL中的UL。从整型常量的词法定义也可看出:

8fd6f7f69095517e154b5928453ad705.png
C整型常量

如果将INT_MIN定义为 -2147483648,这里的 -2147483648 其实是由一元运算符-和常量 2147483648 组成。编译器遇到常量会按照定义好的变量顺序一一匹配其类型(如果指定了后缀,会从指定类型开始匹配),这个定义好的顺序在 C 语言规范文档里可以查到。

5d2cc4ca64456aa84453931bc505939a.png
C十进制类型

常量 2147483648 不带后缀,从int类型开始匹配,因为 2147483648 (2^31) 超过了int的最大取值范围 2147483647(2^31-1),为了保证数值正确性,需要表示范围更大的类型,编译器继续向下匹配到long int,其最大取值范围是 2^63-1 足以表示常量 2147483648,所以常量 2147483648 的最终类型被确定为long int。虽然最小值是正确的,但是类型却不正确,这导致的结果是sizeof INT_MIN的大小是 8 字节而非 4 字节,此外在进行 x < INT_MIN这样的比较操作时,x 会被提升到long int类型,这些显然都是不正确的行为。而如果使用常量-2147483647-1定义INT_MIN,其可以被正确的识别为 int 类型。

下面是一组测试代码,演示了两种表示方法虽然最小值一样,但是类型却不同。

#include 

int main() {
    // 2147483647 在 int 的表示区间内,类型为 int,大小为 4 子节
    printf("%d, %d\n",-2147483647-1,  sizeof(-2147483647-1)); 
    // 2147483648 超出 int 的最大值 2147483647,类型提升为 long int,大小为8子节
    printf("%d, %d\n",-2147483648, sizeof(-2147483648)); 
    return 0;
}

运行结果

-2147483648, 4
-2147483648, 8

小结一下,通过分析 C 标准库中INT_MIN的宏的奇怪定义,发现其中牵扯出了 int 类型的取值范围、常量类型分配、类型提升等知识点。

参考

  • 《深入理解计算机系统》第2章:数据的表示
  • 探究 C 语言标准库 limits.h 关于INT_MIN 宏的奇怪定义
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值