You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
这里涉及到 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.”
C 语言标准库<limit.c>中定义了整型数的最大值和最小值,以 GCC 编译器为例,其定义如下:
这里产生一个疑问:为什么
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
中的U
和L
。从整型常量的词法定义也可看出:如果将
INT_MIN
定义为 -2147483648,这里的 -2147483648 其实是由一元运算符-
和常量 2147483648 组成。编译器遇到常量会按照定义好的变量顺序一一匹配其类型(如果指定了后缀,会从指定类型开始匹配),这个定义好的顺序在 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 类型。下面是一组测试代码,演示了两种表示方法虽然最小值一样,但是类型却不同。
运行结果
小结一下,通过分析 C 标准库中
INT_MIN
的宏的奇怪定义,发现其中牵扯出了 int 类型的取值范围、常量类型分配、类型提升等知识点。参考
The text was updated successfully, but these errors were encountered: