在C语言中,short类型可以存储的最大值和最小值各是多少?

11

我在理解C语言的数据类型方面遇到了一些困难。我正在学习一本C语言书籍,其中一个挑战要求计算一个short类型可以存储的最大和最小值。

使用sizeof(short);可以看到一个short类型占用2个字节。这意味着它是16位,可以存储两个数字,因为一个数字的二进制表示需要8位。例如,9将是00111001,占用了一位。所以对于无符号数来说,范围不应该是0到99吗?带符号数则是-9到9?

我知道我是错的,但我不确定为什么。这里说最大值为(-)32,767(有符号)和65,535(无符号),可以点击这里查看更多信息。

short int,2个字节,16位,范围为-32,768 -> +32,767(16kb)


2
16位意味着您有16个可以打开和关闭的开关。不同的开关组合总数为2^16,即65536种不同的状态。 - nhahtdh
1
只是出于好奇,标准允许的范围是多少? - Antimony
@Antimony 请查看Richard J. Ross III的答案中的链接:{SHRT_MAX}。 类型short的最大值。 最小可接受值:+32 767。 - Kijewski
请记住,尽管65536 = 2^16,但根据limits.h的最大限制是65535,因为65536被视为溢出。 - kiranputtur
5个回答

18
请用十进制思考一下。如果一个数字只有两位数,那就意味着你可以在其中存储从 0099 的数字。如果你有四位数,这个范围就变成了 00009999
二进制数与十进制数类似,不同之处在于它们的数字只能是 01,而不是 0123、……、9
如果你有一个像这样的数字:
01011101

这是:

0*128 + 1*64 + 0*32 + 1*16 + 1*8 + 1*4 + 0*2 + 1*1 = 93

所以,您可以看到,一个字节可以存储比9更大的值。在无符号8位数中,实际上可以存储从00000000到11111111的值,这在十进制中是255。
在2个字节的数字中,此范围变为从0000000000000000到1111111111111111,这恰好是65535。
您的描述“用8位存储数字的二进制表示”就像说“用8位数存储数字的十进制表示”,这是不正确的。例如,数字12345678901234567890具有超过8个数字。同样,您不能将所有数字都放入8位中,而只能放置其中256个。这就是为什么您会得到2字节(short),4字节(int)和8字节(long long)数字。事实上,如果您需要更高范围的数字,则需要使用库。
只要涉及负数,在2的补码计算机中,它们只是一种惯例,使用范围的高半部分作为负值。这意味着左侧有1的数字被认为是负数。
尽管如此,这些数字256(如果有n位,则模2^n),与其真正表示的正值模数相同。例如,数字11111111在无符号情况下为255,在有符号情况下为-1,它们在模256的意义下是相等的。

好的!谢谢。我明白了。我必须用“二进制”数字来思考,而不是十进制。现在有意义了。我的理解完全错了! - Mohamad
@Mohamad,没错。这与十进制非常相似。每当你感到困惑时,你可以使用这个类比来更好地理解 ;) - Shahbaz

11

您所阅读的参考资料是正确的。至少对于通常使用16位short 的C实现来说是如此 - 标准中实际上并没有固定这一点。

16位可以容纳2^16个可能的比特模式,即65536种可能性。有符号short是-32768到32767,无符号short是0到65535。


但是存储一个数字需要8位,对吧?16位可以存储2个数字?我在这里漏掉了什么! - Mohamad
@Mohamad 一个比特足以存储范围在[0;1]之间的数字。两个比特可以存储4个数字。依此类推... - Kijewski
@Mohamad:不是的。8位只能存储0-255范围内的数字。16位可以存储0-25535范围内的数字。32位(通常为“int”)可以存储大约40亿个数字。你明白了吧。这都是二的幂次方。 - Linuxios

9
这在<limits.h>中定义,分别为SHRT_MINSHRT_MAX

4
楼主显然在理解二进制数字方面存在问题。那么这怎么能帮助他理解呢? - Shahbaz
2
@Shahbaz:这不会让他理解,但它确实给了他一些简单的十进制数。在编写可移植程序时,<limits.h>也可以是非常有价值的工具,谁知道这是否是问题核心所在?这个问题在回答中恰到好处地平衡了理论和实用性。 - Linuxios

3
其他人已经为您发布了相当好的解决方案,但我认为他们没有遵循您的思路并解释您错在哪里。我来试试。
我可以看到一个short占用2个字节。这意味着它是16位,
到目前为止,您是正确的(尽管short不能像int一样保证长度为2个字节,char应该始终为1字节宽,这是标准中唯一保证的大小(如果我记得正确))。
从这里开始,您有点偏离了。实际上,并非每个数字都需要8位来存储。根据数字的不同,可能需要16、32、64甚至更多位来存储。将您的16位分成2部分是错误的。如果不是CPU实现的特定情况,我们可能会有例如2位数字。在这种情况下,这两个位可以存储值:
00 - 0 in decimal
01 - 1 in decimal
10 - 2 in decimal
11 - 3 in decimal

为了存储数字4,我们需要3个二进制位。因此,该值“无法容纳”,导致溢出。16位数字也是如此。例如,假设我们有一个以十进制表示为“255”的无符号数存储在16位中,则二进制表示为0000000011111111。将其加1后变成0000000100000000(十进制中的256)。因此,如果您只有8位,则会溢出并变为0,因为最高有效位将被舍弃。

现在,在16位内存中,您可以使用的最大无符号数字为- 1111111111111111 ,这是65535的十进制表示。换句话说,对于无符号数字-将所有位设置为1,这将产生最大可能的值。

对于有符号数字,最高有效位表示符号-正数为0,负数为1。对于负数,最大值为1000000000000000 ,这在基数10中为-32678。有关有符号二进制表示的规则在此处描述得很好。

希望这能帮助您!


谢谢你那么棒的解释。我无法在你和Shahbaz之间做出选择,但是感谢你跟随我的思路! - Mohamad
不客气!我自己也被这些事情困惑了 :) 所有东西都是十进制的 :-D - user405725

1

找到任何无符号二进制表示数范围的公式:

2 ^ (sizeof(type)*8)

2
<< 是左移位运算符。如果你将一个1位向左移动n位,你会得到2的n次方。在C语言中,^ 表示按位异或。 - Kijewski
@Kay:谢谢。我不知道二的幂可以只是左移。评论+1? - Linuxios
这不是正确的。在C语言中,整数可能会有填充。 - 2501
@2501:是对于理论计算机不正确,还是对于C标准不正确? - Linuxios
C标准允许在整数中填充位。您无需使用理论计算机来展示这一点,在现代体系结构中至少会发生在一个类型中。 - 2501

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接