C语言 | 有符号整型与无符号整型 格式化输出十进制整型
一 有符号整型与无符号整型
(一)存储空间
长整型、基本整型、短整型分别在内存中占据不同的字节数。在64位系统中,长整型和基本整型占据4个字节(32位),短整型占据2个字节(16位)。
为了节约内存空间,在定义整型变量时建议采用占据字节数尽可能小的类型。
(二)符号位 原码、反码、补码
在不加修饰的条件下,计算机默认整型为有符号整型。对于有符号整型而言,其对应二进制数的最高位是符号位,并且0表示正数,1表示负数。
二进制数的表示方法分为3种:原码、反码、补码。计算机总是以补码的形式存储数。对于正数而言,原码、反码、补码均相同,三者均表示数的真值。对于负数而言,原码除符号位以外的位表示绝对值,反码是对原码除符号位以外的位取反的结果,补码是反码加1的结果。如下例:
1 |
|
在64位系统中,基本整型占据4个字节,因此变量e被赋值0后在内存中存储了32位0。按位取反后,32位0变为32位1。32位1的符号位是1,表示其为负数,其原码最高位(符号位)和最低位为1,其余位为0,所以真值为-1。
为什么计算机要使用补码来存储负数?
从原理上而言,加法和减法要依靠不同的电路实现,如果能将减法运算转化为加法运算,就能简化电路。同时,如果使用原码进行含负数的加法运算,其结果总是错误的。例如(-2) + 1 = 1000 0010 + 0000 0001 = 1000 0011 = -3(错误)。
计算机中的计数是可溢出的。譬如对1字节而言,有符号数的最大值是0111 1111,即127,再加1将溢出,使得最高位同时表示数值和符号,结果是1000 0000,为负数的补码;其原码为1000 0000(最高位仍然同时表示数值和符号),即-128。
一周共7天,周四至周六的计算可以是+2,也可以是-5,甚至可以是+9,-12,+17,-19等,这样的计算都是等价的,意味着对于可溢出系统而言,总能够使用加法代替减法运算。设可溢出系统的模为N(例如这里是7),那么加数和减数的和始终为N,这样的关系称为补数。
类似地,对于1字节而言,其模是1 0000 0000,若计算(-2) + 1,那么首先将-2转化为其补数。先取-2的绝对值2,然后用模减之,即1 0000 0000 - 0000 0010 = 1111 1110。因此(-2) + 1 = 1111 1110 + 0000 0001 = 1111 1111(补) = -1(正确)。
(三)有符号整型与无符号整型的定义和区别
不加修饰时,系统默认整型为有符号整型。无符号整型的表达在常量中为后缀U或u,在变量中则加关键字unsigned。它们的区别在于有符号整型的最高位是符号位,其余位表示数值,1字节的有符号整型的取值范围是[-128,127];无符号整型每一位都表示数值,1字节的无符号整型的取值范围是[0,255]。
二 格式化输出十进制整型
在变量中,整型分为长整型、基本整型和短整型,它们各自又分为有符号整型和无符号整型。每一种类型都有各自的格式控制字符串。就十进制而言,它们的格式控制字符串如表T1所示。
| 整型类型 | 格式控制字符串 |
|---|---|
| 有符号长整型 | "%ld" |
| 无符号长整型 | "%lu" |
| 有符号基本整型 | "%d" |
| 无符号基本整型 | "%u" |
| 有符号短整型 | "%hd" |
| 无符号短整型 | "%hu" |
T1.十进制整型的格式控制字符串
以下就有/无符号基本/短整型为例,形象地体现了它们的区别。
1 |
|
