数据类型(二)及编码
文章目录
1. char类型
1.1 基础信息
-
名称:字符型。
-
单位:一个字节(8 bit位)。
-
格式匹配符:
- 数值型:
- 有符号:%hhd —— char 显示数值专用格式匹配符。
- 无符号:%hhu —— unsigned char 显示数值专用格式匹配符。
- 字符型:
- %c
- 数值型:
-
取值范围:
- 有符号: -128 ~ 127
- 无符号:0 ~ 255
-
程序获取
#include <stdio.h> #include <limits.h> int main(void) { // 获取无符号数取值范围 printf("char 无符号 min = 0,max = %hhu\n", UCHAR_MAX); // 获取有符号数取值范围 printf("char 有符号 min = %hhd,max = %hhd\n", CHAR_MIN, CHAR_MAX); // 获取 char 占用的字节数 printf("char 大小 = %u\n", sizeof(char)); // 获取 unsigned char 占用的字节数 printf("unsigned char 大小 = %u\n", sizeof(unsigned char)); return 0; }
2. ASCII码
2.1基本信息
- char 类型数据,数值 对应一个 ASCII 码。
- ASCII表:
#include <stdio.h>
int main(void)
{
char ch = 'A'; // 定义变量 ch, 指定初值为 'A';
printf("ch = %c\n", ch); // c: character %c 用来显示字符的 格式匹配符。
ch = 'm'; // 给变量ch 赋值成 'm', 覆盖 原来的 'A';
printf("ch = %c\n", ch);
ch = 97; // 使用 范围内的数值 97 ,给 ch 赋值。
printf("ch = %c\n", ch); // 将数值97,按照字符格式打印输出。
ch = 98; // 使用 范围内的数值 98 ,给 ch 赋值。
printf("ch = %c\n", ch); // 将数值98,按照字符格式打印输出。
return 0;
}
2.2 练习:
- 将 大写字母,转换成 小写字母。
#include <stdio.h>
int main(void)
{
char ch = 'R'; // char 变量定义
printf("R 转换的小写为:%c\n", ch+32); //ch+32 表达式,对应格式匹配符 %c
char ch2 = 'h'; // char 变量定义
printf("h 转换的大写为:%c\n", ch2-32); //ch2-32 表达式,对应格式匹配符 %c
char ch3 = '5';
// 借助字符5, 利用 ASCII特性,打印出 字符9
printf(" 打印字符9 = %c\n", ch3+4);
return 0;
}
2.3 ASCII表说明
- 0 ~ 32 ASCII码 对应的字符都不可见。
- 常用的 ASCII码:
- ‘a’:ASCII码值 97
- ‘A’:ASCII码值 65
- ‘0’:ASCII码值 48
- ‘\n’ ASCII码值 10
- ‘\t’ 制表符。tab键对应的字符。(ASCII码值 9)
- ‘\0’ ASCII码值 0
2.4 练习:
- 在一个printf函数中, 打印输出
hello 换行 world 换行
。
// 方法1
int main(void)
{
printf("hello\nworld\n");
return 0;
}
// 方法2
int main(void)
{
char ch = '\n'; //定义ch变量,初值为'\n'
printf("hello%cworld%c", ch, ch); // 等价于 printf("hello\nworld\n");
return 0;
}
方法3
int main(void)
{
char ch = 10; //定义ch变量,初值为'\n'
printf("hello%cworld%c", ch, ch); // 等价于 printf("hello\nworld\n");
return 0;
}
- 一个printf中打印
hello (一个tab缩进) world 换行
int main(void)
{
char ch1 = '\t'; // 实现 一个tab缩进
char ch2 = '\n'; // 实现 一个换行。
printf("hello%cworld%c", ch1, ch2);
return 0;
}
3. 转义字符
3.1 基本信息
- ‘/’: 自右向左划, 叫做 “斜杠”。
- ‘\’ : 自左向右划,叫做 “反斜杠” 。 ——是 转义字符。
- 转义字符的作用:
- 将普通字符,转换为 特殊意。
- 如: ‘\n’ : 这是一个字符。代表换行。
- 如:‘\t’ : 这是一个字符。代表 一个制表符。
- 将特殊字符,还原成本身意。
- 如:
\\n
: 这样就将 一个字符 ‘\n’,还原成 两个字符:‘\’ 和 ‘n’
- 如:
- 将普通字符,转换为 特殊意。
3.2 练习
- 将 特殊字符转换成本身意。
题目:屏幕上严格输出 如下内容:【 ‘\n’ 的值是 10】 要求显示时要有 ‘ ’
int main(void)
{
printf("'\\n'的值是 %hhd", '\n');
return 0;
}
4.实型(浮点型)
4.1 基础信息
-
显示小数。
-
float : 单精度浮点型。 %f 大小:4字节。( 可以使用 sizeof() 求取 )
- float = 4.35 默认会被编译器理解为 double 类型。
- float v = 4.567f; 编译器理解 float。
- %f 格式匹配符,默认保留6位小数。
-
double: 双精度浮点型。%lf 大小:8字节。
- double d = 5.68;
4.2 取值范围
- 使用头文件 #include <float.h> 获取浮点型取值范围。
int main(void)
{
printf("float 范围:%f ~ %f\n", FLT_MIN, FLT_MAX);
printf("double 范围:%lf ~ %lf\n", DBL_MIN, DBL_MAX);
return 0;
}
- 求取的结果:
4.3 精度问题
- float类型:
- 精度 6~7 位:
- 整数部分 + 小数部分 <= 6 位, 准确。
- 整数部分 + 小数部分 == 7 位,可能准确,也可能不准确。
- 整数部分 + 小数部分 > 7位。不准确。
- 精度 6~7 位:
- double类型
- 精度 15~16 位:
- 整数部分 + 小数部分 <= 15 位, 准确。
- 整数部分 + 小数部分 == 16 位,可能准确,也可能不准确。
- 整数部分 + 小数部分 > 16位。不准确。
- 精度 15~16 位:
-
不同平台(操作系统),对应float、double 类型实现的精度有可能不同。以上是Windows 下 特性。
-
float 和 double 不存在 “无符号”类型。
5. bool 类型
- C语言原来没有 bool 类型。 C99标准中,新增了 bool 类型。C++ 自带 bool类型。
- 用处:
- 表示 :
- 好、坏
- 真、假
- 对、错
- 是、否
- 取值:
- true —— 真 —— 1
- false —— 假 —— 0
- 表示 :
- C语言使用bool 的条件:
- 编译器要支持c99标准。
- 导入 #include <stdio.h>
- bool 类型的大小。
- 1字节。 ( sizeof() 求取 )
- bool 没有专用的格式匹配符。 打印时,使用 %d 来打印。
- true —— 真 —— 1
- false —— 假 —— 0
int main(void)
{
bool aa = true; // 定义bool 类型变量 aa , 初值为 true == 1
printf("aa = %d\n", aa);
aa = false; // 给 bool 类型变量 aa 赋值为 false == 0
printf("aa = %d\n", aa);
return 0;
}
6. 进制和转换
- 计算机 只 使用 2 机制。
- 8进制、10进制、16进制。统统都是给人类用的!!!
6.1 存储知识
- 1 bit位 就是一个 二进制位。 存 0 或 1
- 一个字节(Byte) 1B = 8bit位。
- “内存单元” 是计算机内存存储的最小单位, 一个内存单元 == 1字节。
- 1KB = 1024B
- 1MB = 1024KB
- 1GB = 1024MB
- 1TB = 1024GB
6.2 二进制
-
取值 1 或 0. 逢 2进 1。 借 1 当 2 。
-
没有格式匹配符
6.2.1 十进制 转 二进制
- 除 2 反向取余法
6.2.2 二进制转十进制
-
掌握 20 ~ 210 各自的取值:
- 20 : 1
- 21 : 2
- 22 : 4
- 23 : 8
- 24 : 16
- 25 : 32
- 26 : 64
- 27 : 128
- 28 : 256
- 29 : 512
- 210 : 1024
-
计算方法,对应二进制位,有1 累加2的指数次幂值,有 0 略过。
- 11101 —— 29
- 10110 —— 2+4+16 = 22
6.3 八进制
- 逢 8 进 1。 借1当8。
- 取值: 0/1/2/3/4/5/6/7 最大值 7
- 格式匹配符:%o 和 %#o(带#的输出时十六进制数字前带有0)
- 表示语法: 0开头 。
- 8 进制 ——> 10 进制:
- 056 == 80 * 6 + 81 * 5 = 6 + 40 = 46
- 0123 = 80 * 3 + 81 * 2 + 82 * 1 = 3 + 16 + 64 = 83
- 10 进制 ——> 8进制:
- 除 8 反向取余法
- 135 —— 0207
- 除 8 反向取余法
6.3.1 八进制转二进制
- 转换算法: 将 8进制数,自左向右,每一位,用 421 码 展开。
- 练习:
- 056 —— 101110
- 04735 —— 1001 1101 1101
- 053261 —— 101 0110 1011 0001
详细剖析:如056中,5是由421中的一个4一个1组成,也就是说421这三个数字的个数为1、0、1组成了5,那么5就是101。6是由421中的一个4一个2组成,也就是说421这三个数字的个数为1、1、0组成了6,那么6就是110。所以056的八进制=101110的二进制。
6.3.2 二进制转八进制
-
转换方法:自右向左,每3个二级制位一组, 不足3位补0 。
-
1101010101111010
- 分组:1 101 010 101 111 010
- 补齐:001 101 010 101 111 010
- 八进制数为:0152572
-
10110111011
- 分组:10 110 111 011
- 补齐:010 110 111 011
- 八进制数为:02673
-
6.4 十六进制
- 逢 16 进 1。 借1当16。
- 取值: 0~9 10-A/a 11-B/b 12-C/c 13-D/d 14-E/e 15-F/f 最大值: F/f
- 格式匹配符:%x 或 %#x(带#的输出时十六进制数字前带有0x)
- 表示语法: 0x开头 。
- 16 进制 ——> 10 进制:
- 将每一个16进制位,展开 相加得 10进制。
- 10 进制 ——> 16进制:
- 除 16 反向取余法
- 37:0x25
- 43:0x2B
- 除 16 反向取余法
6.4.1 十六进制转二进制
- 转换算法: 将 16 进制数,自左向右,每一位,用 8421 码 展开
- 0xFAC12 : 1111 1010 1100 0001 0010
详细剖析:F是15,他是由8421中的一个8一个4一个 2一个1组成,即1111,A是10,是由8421中1个8一个2组成,所以是1010,
6.4.2 二进制转十六进制
- 转换方法:自右向左,每4个二级制位一组, 不足4位补0 。
- 101001011101011001
- 分组:10 1001 0111 0101 1001
- 补齐:0010 1001 0111 0101 1001
- 16进制数为:0x29759
- 1110110100111101
- 分组:1110 1101 0011 1101
- 补齐:1110 1101 0011 1101
- 16进制数为:0xED3D
- 101001011101011001
6.5 小结
- 使用频率最高的是 10 进制。 次高的:16进制。
- int m = 0x15F4;
- int n = 0345;
- int k = 0101101;
- 不能直接将变量值赋值为 2进制。
- 上述的赋值,会被编译器理解为 8进制数。
#include <stdio.h>
int main(void)
{
int a = 56; // 10进制数作a变量初始化。 —— 定义。
printf("10进制:a = %d\n", a);
printf("8进制:a = %o\n", a);
printf("8进制:a = %#o\n", a); //在%和x中间添加#,可以在输出时,显示8进制前缀。
printf("16进制:a = %x\n", a);
printf("16进制:a = %#x\n", a); //在%和x中间添加#,可以在输出时,显示16进制前缀。
return 0;
}
7. 常用的格式匹配符
- %d
- %c
- %x
- %u
- %s (后续课程讲,打印字符串)
- %o
- %#o
- %#x
- %hhd
- %hd
- %ld
- %lld
- %hhu
- %hu
- %lu
- %llu
- %f
- %lf
8. 编码和存储
8.1 无符号存储
unsigned int a = 12; // 占用 4 字节 32 个 bit位存储。
空间:00000000 00000000 00000000 00000000 ———— 4 字节。
存储:00000000 00000000 00000000 00001100
unsigned short b = 15; //占用 2 字节 16 个 bit位存储。
空间:00000000 00000000 ———— 2 字节。
存储:00000000 00001111
8.2 有符号存储
- 需要拿出一个二进制位,专门存储符号。标识正、负。
- 选用 最高位 为符号位。
- 正:0
- 负:1
8.2.1 有符号正数
// 采用 “源码” 存储
int a = 5;
空间:0 0000000 00000000 00000000 00000000
存储:0 0000000 00000000 00000000 00000101 --- 表示存储正数 5 。
8.2.3 有符号负数
- 有符号的负数,采用 “补码” 存储
- 源码:数值的二进制位直接存储。
- 反码:符号位不变,将其余数值为取反。
- 补码:反码+1。
int b = -33;
空间:0 0000000 00000000 00000000 00000000
源码:1 0000000 00000000 00000000 00100001
反码:1 1111111 11111111 11111111 11011110
补码:1 1111111 11111111 11111111 11011111 —— 负33 在计算机中实际的存储形式。
-
小结:
- int —— 4字节 —— 32bit位
- 有符号:31个数值位。 取值范围 -231 ~ 231 -1 ——> -2147483648 ~ +2147483647
- 无符号:32个数值位。取值范围 0 ~ 232 -1 ——> 0 ~ 4294967295
- short —— 2字节 —— 16bit位
- 有符号:15个数值位。 取值范围 -215 ~ 215 -1 ——> -32768~32767
- 无符号:16个数值位。取值范围 0 ~ 216 -1 ——> 0 ~ 65535
- int —— 4字节 —— 32bit位
-
因此,知道数据类型占用内存的大小,就能算出该类型 无符号数、有符号数 对应的取值范围。
诚挚感谢传智播客王飞老师的讲解以及提供的素材。