本节必须掌握的知识点:
示例十
代码分析
汇编解析
3.5.1 示例十
char类型是比较古怪的,int\short\long类型如果在使用时不指定signed还是unsigned时都默认是signed,但char不一样,编译器可以实现为带符号的,也可以实现不带符号的。说它是字符类型,但它可以存储【-128~127】或【0~255】之间的整数,其中0~127对应ASCII码字符。
char的取值范围如下表所示:
类型 | 存储大小 | 值范围 |
char | 1字节 | 【-128~127】或【0~255】 |
signed char | 1字节 | 【-128~127】 |
unsigned char | 1字节 | 【0~255】 |
表3-7 char类型取值范围
示例代码十
/*
输出char类型的值
*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char c = 1;
printf("c = %d\n", c);
system("pause");
return 0;
}
●输出结果:
c = 1
请按任意键继续. . .
3.5.2 代码分析
■char c = 1;
char类型在VS编译器中的取值范围是-128~127。示例十中定义了char型变量c:
char c = 1;
紧接着printf函数按整数型格式化说明符’%d’输出变量c。输出结果为c = 1。
如果将printf函数的格式说明符改为’%c’,输出结果将变为:
这是整数值1对应的ASCII字符。
■char c = 255;
’%c’输出结果将变为:
超出了ASCII字符的范围。
■char c = EOF;
’%c’输出结果将变为:
EOF结束符的值为-1。VS中选中EOF,鼠标右键选择“速览定义”:
#define EOF (-1)
3.5.3 汇编解析
■汇编代码
;C标准库头文件和导入库
include vcIO.inc
.data
chr sbyte 1 ;sbyte等价于char类型
.const
szMsg db "c = %c",0dh,0ah,0
.code
start:
invoke printf,offset szMsg,chr
;
invoke _getch
ret
end start
●输出结果:
在MASM汇编器中,sbyte类型为8位有符号整型,等同于C语言中的char类型,取值范围为-128~127。
■反汇编代码
char c = 1;
00231838 mov byte ptr [c],1
printf("c = %c\n", c);
0023183C movsx eax,byte ptr [c]
00231840 push eax
00231841 push offset string "c = %c\n" (0237B30h)
00231846 call _printf (023104Bh)
0023184B add esp,8
在反汇编代码中,char c = 1;翻译为汇编语句为:mov byte ptr [c],1,这里使用的是临时强制指定数据宽度为byte类型。
如果改为char c = 1;翻译为汇编语句为:mov byte ptr [c], 0FFh,编译器将-1转换为补码形式存储。
实验三十一:输出char类型占用的存储空间以及它的范围值
VS中新建项目3-5-2.c。需要引用limits.h标准库函数头文件。代码如下:
/*
输出char类型占用的存储空间以及它的范围值
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
printf("char 存储大小 : %u byte\n", sizeof(char));
printf("unsigned char 存储大小 : %u byte\n", sizeof(unsigned char));
printf("the range of char: %d ~ %d\n", SCHAR_MIN, SCHAR_MAX);
system("pause");
return 0;
}
●输出结果:
char 存储大小 : 1 byte
unsigned char 存储大小 : 1 byte
the range of char: -128 ~ 127
请按任意键继续. . .
实验三十二:输出char类型字符及其ASCII值
VS中新建项目3-5-3.c。需要引用limits.h标准库函数头文件。代码如下:
/*
输出char类型字符及其ASCII值
*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char a = 'E';
char b = 70;
int c = 71;
int d = 'H';
printf("a=%c, a=%d\n", a, a);
printf("b=%c, b=%d\n", b, b);
printf("c=%c, c=%d\n", c, c);
printf("d=%c, d=%d\n", d, d);
system("pause");
return 0;
}
●输出结果:
a=E, a=69
b=F, b=70
c=G, c=71
d=H, d=72
请按任意键继续. . .
●观察反汇编代码:
char a = 'E';
000C1838 mov byte ptr [a],45h
char b = 70;
000C183C mov byte ptr [b],46h
int c = 71;
000C1840 mov dword ptr [c],47h
int d = 'H';
000C1847 mov dword ptr [d],48h
结论:char类型变量在内存中存储的都是-128~127之间的整数值。
练习
- 请读者将3-5-3.c翻译成汇编语言实现。
- 请读者分析3-5-3.c的反汇编代码。
实验三十三:判断char类型有无符号
VS中新建项目3-5-4.c。代码如下:
/*
判断char类型有无符号
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
puts("这个编译器中的char型是:"); //有符号的
if (CHAR_MIN)
{
puts("有符号的。"); //不为0,
}
else
{
puts("无符号的。");
}
system("pause");
return 0;
}
●输出结果:
这个编译器中的char型是:
有符号的。
请按任意键继续. . .
结论
1.char型是用来保存“字符”的数据类型。
2.对于没有声明signed还是unsigned的char型,视为有符号类型还是无符号类型,视编译器而定。
3.注意:'c'和'\n'等字符常量为int型。不是char型。
练习
- 请读者将3-5-4.c翻译成汇编语言实现。
请读者分析3-5-4.c的反汇编代码。
本文摘自编程达人系列教材《汇编的角度——C语言》。