K& R在C编程语言中有一个练习,可以找到各种类型的最大/最小值,例如char和int。
在下面的代码中:
#include<stdio.h>
#include<limits.h>
void main()
{
printf("Size of Char Max %d\n", CHAR_MAX);
printf("Max Char+1 = %d\n",CHAR_MAX+1); //my test code
}
因为CHAR_MAX
是127,这是类型char
的最大值,为什么不向它添加1会导致溢出?
答案 0 :(得分:5)
首先,char
的范围是-128到127还是0到255或其他完全是实现定义的。该标准没有定义char
是signed
还是unsigned
,也没有定义它必须有8个二进制位,尽管后者在今天的实践中可以安全地假设。见ISO / IEC 9899:1999中的3.9.1(1):
(...)实现定义
char
对象是否可以保存负值。 (...)
唯一的保证是CHAR_MIN
不大于0而CHAR_MAX
不小于127(附件E)。
至于添加,您不会出现溢出,因为CHAR_MAX
和1
(以及11
)都是int
,而不是char
},所以不能期望溢出。
此外,甚至还有
char c = '\x7f';
c + c;
(即char + char
)的类型为int
,即使char
为signed
也不会溢出,因为通常的算术转换已应用到+
的操作数。简而言之,这些表明在算术运算中,所有操作数都被转换为最大的相关类型,并且整数提升也应用于整数类型。整体促销说明,在应用它们的情况下,小于int
的整数类型最多转换为int
,因此我们再次int + int
并且没有溢出。
关于第一段中“八位二进制位”注释的附录/附注:作为历史意义问题,该问题超出了数据类型甚至在二进制计算机上的位数。它在今天几乎没有实际意义,但C是在并非所有普通计算机都使用整数的二进制补码表示的时候编写的。因此,附件E中签名类型的实施限制是对称的(例如,INT_MAX <= 32767
和INT_MIN >= -32767
而不是-32768)。在使用一个补码或有符号幅度表示的机器上,我们习惯的不对称就不存在,并且有两个零值(0和-0)。
答案 1 :(得分:2)
您正在以整数类型(%d)打印CHAR_MAX
的值。因此它会将值打印为
在整数数据类型中。
char
的总范围为-128 to 127
。
对于整数是四个字节。所以没有溢出。
你可以试试这个。
char a=256;
当您这样指定时,您将获得警告。
warning: overflow in implicit constant conversion [-Woverflow]
答案 2 :(得分:1)
CHAR_MAX
in被定义为宏常量,而不是您正在考虑的类型char
。看看here。
在printf("Max Char+1 = %d\n",CHAR_MAX+1);
中,预处理器会将CHAR_MAX
替换为127
。由于127 + 1是128,格式说明符是%d
(int),所以没有溢出。
答案 3 :(得分:0)
你的想法是正确的:
printf("Max Char+1 = %d\n",(char)(CHAR_MAX+1));
让我们回顾一下这行代码:
int
的{{1}}值等于0x00000080(128)CHAR_MAX+1
时,会被截断为char
值0x80(-128)char
时,会扩展为printf
值0xFFFFFF80(-128)由于您未在代码中将其强制转换为int
,因此将char
值0x00000080传递给int
“。”
上面的答案是假设您的平台上printf
为8且CHAR_BIT
为4。