《C Primer Plus 》例题解析 程序清单 4.11 intconv.c 程序
/*intconv.c —— 一些不匹配的整型转换*/
#include<stdio.h>
#define PAGES 336
#define WORDS 65618
int main(void)
{
short num = PAGES;
short mnum = -PAGES;
printf("num ad short and unsigned short: %hd %hu\n", num, num);
printf("-num as short and unsigned short: %hd %hu\n", mnum, mnum);
printf("num as int and char: %d %c\n", num, num);
printf("WORDS as int, short, and char: %d %hd %c\n", WORDS, WORDS, WORDS);
return 0;
}
运行结果:
num ad short and unsigned short: 336 336
-num as short and unsigned short: -336 65200
num as int and char: 336 P
WORDS as int, short, and char: 65618 82 R
解析:
printf("num ad short and unsigned short: %hd %hu\n", num, num);
short num = 336
整数有符号取值范围(n表示位):[-2^(n-1), 2^(n-1) -1]
整数无符号取值范围(n表示位):[0, 2^n -1]
short 占2字节,16位,所以short:
有符号整型取值范围 [-32768,32767]
无符号整型取值范围 [0,65535]
336 在取值范围里面,所以%hd(short有符号整型)输出336,%hu(short无符号整型)输出336
printf("-num as short and unsigned short: %hd %hu\n", mnum, mnum);
mnum = -336 没有超出 short有符号整型取值范围 [-32768,32767],所以%hd 输出-336
这里求%hu 用了两种方法 ,方法1:将short无符号整型换成有符号整型是可以这样理解,0-32767代表它本身,32768-65535代表负数,其中
-1 代表(65536 -1)
-2 代表 (65536 - 2)
-3 代表 (65536 -3)
以此类推, -336 代表(65536 -336)= 65200 ,所以%hu 输出65200
方法2:-336 的原码是 1000 0001 0101 0000
-336的反码是 1111 1110 1010 1111
-336的补码是 1111 1110 1011 0000
计算机里存的是补码 1111 1110 1011 0000,转换成无符号整型的十进制就是65200
printf("num as int and char: %d %c\n", num, num);
short num = 336
int 占4字节,short 占2字节,336没有超出int 的取值范围,所以%d输出336
char 占1个字节,这就需要将16位的数截断为8位
336的二进制:0000 0001 0101 0000
只取后8位是: 0101 0000,转换成十进制就是 80,%c表示打印这个数值对应的字符,所以输出P
按照这种方法,每次都要先把二进制写出来有点麻烦,所以可用截断原则:在哪里截断就除以2的n次方,然后取其余数。此处为 ,将336除以256后取其余数,336又被解释为“以256"为模。
printf("WORDS as int, short, and char: %d %hd %c\n", WORDS, WORDS, WORDS);
WORDS = 65618 没有超出int的取值范围,所以%d输出 65618
WORDS 是int类型,要将其转换成short类型需要截断,在哪里截断就除以2的n次方,然后取其余数, 此处为 ,所以%hd输出82
将WORDS转换成char类型也需要截断,在哪里截断就除以2的n次方,然后取其余数, 此处为,82对应的ASCII码是R,所以%c输出R