数据存储,常量和变量

1. 数据存储

1.1 计算机硬件基本知识

对于程序开发中,计算中重要的硬件组成是 CPU,内存(RAM)和硬盘(ROM)。任何的程序运行都需要 CPU 提供对应的执行能力和运算能力,同时内存提供程序的执行数据空间,硬盘作为永久性数据存储设备完成数据存储。

1.2 计算机中最小数据存储单位

计算机中规定,最小的数据存储单位是【字节 byte】,一个字节对应 8 个二进制位/ bit 位,嵌入式开发中常用的数据存储单位

  • KB ==> 1024 Byte
  • MB ==> 1024 KB
  • GB ==> 1024 MB

正常开发中常用数据单位一般是 KB 和 MB ,后续到驱动开发或者较大型的嵌入式项目开发涉及到 GB 单位

1.3 开发中的常用数据进制

在嵌入式开发中,常用的数据进制有

  • 十进制
  • 二进制
  • 八进制
  • 十六进制

进制仅是当前数据的描述形式和描述方法。

1.3.1 不同进制数据的使用要求或者文本描述要求
数据进制 基数范围 进制关系
十进制 0 ~ 9 逢 10 进一
二进制 0,1 逢 2 进一
八进制 0 ~ 7 逢 8 进一
十六进制 0 ~ 9, A ~ F 逢 G(16) 进一

tips:A => 10, B => 11, C => 12, D => 13, E => 14, F => 15

十进制使用

  • 正常使用和生活中数学十进制使用形式一致。

八进制使用

  • 【要求】在开发中八进制数据要求 0 开头,告知编译器当前数据为八进制数据
  • 【特殊】在特定情况下,0 可以省略,例如 chmod 775
0777 0666 0123

十六进制【重点】

  • 【要求】在开发中十六进制数据要求 0x 开头,告知编译器当前数据为十六进制数据
  • tips: 十六进制使用的英文字母 A ~ F,不区分大小写
0xABCD 0x1234 0xab123df

二进制

  • 【要求】开发中一般情况下不会直接使用二进制数据形式,通常情况下会采用十六进制方式来描述二进制数据内容,当前数据形式为【文档中的数据展示形式】
  • 一般情况下二进制 4 位为一个组合,8 位为一个整体,另外为了明确告知,通常情况下会结尾使用 (2) 告知当前文本数据为二进制数据内容
0110 1100(2) # 文档中描述二进制的推荐形式,开发中无法使用
0011 1011 1100 1000(2)
1.3.2 不同进制之间的转换

进制转换中最重要的是

  • 【重点,掌握】十六进制和二进制之间转换
位号 3 2 1 0
数值 8 4 2 1

A => 10, B => 11, C => 12, D => 13, E => 14, F => 15

十六进制的一位对应二进制的四位

案例一: 十六进制转二进制

0x9FDE
#十六进制的每一位数据分析对应数值,使用二进制 0 ~ 3 位数据进行累加计算,哪一位使用,哪一位为 1
# 9 ==> 8 + 0 + 0 + 1 ==> 1001
# F(15) ==> 8 + 4 + 2 + 1 ==> 1111
# D(13) ==> 8 + 4 + 0 + 1 ==> 1101
# E(14) ==> 8 + 4 + 2 + 0 ==> 1110
二进制结果为
 1001 1111 1101 1110(2)

案例二: 二进制转十六进制

1101 1110 1010 1000(2)
# 1101 ==> 8 + 4 + 0 + 1 ==> 13 ==> D
# 1110 ==> 8 + 4 + 2 + 0 ==> 14 ==> E
# 1010 ==> 8 + 0 + 2 + 0 ==> 10 ==> A
# 1000 ==> 8 + 0 + 0 + 0 ==> 8  ==> 8
十六进制结果为
	0xDEA8
  • 八进制和二进制之间转换
位号 2 1 0
数值 4 2 1
  • 八进制的一位对应二进制的三位

案例一: 八进制转二进制操作

07562
# 7 ==> 4 + 2 + 1 ==> 111
# 5 ==> 4 + 0 + 1 ==> 101
# 6 ==> 4 + 2 + 0 ==> 110
# 2 ==> 0 + 2 + 0 ==> 010
二进制结果为
	0000 1111 0111 0010(2)

案例二: 二进制转换八进制操作

0110 1100 1011 0111(2)
# 按照八进制一位对应二进制三位规则,从数据末尾开始拆解二进制内容
000 110 110 010 110 111
# 从前向后进行 二进制转换进制操作
# 110 ==> 4 + 2 + 0 ==> 6
# 110 ==> 4 + 2 + 0 ==> 6
# 010 ==> 0 + 2 + 0 ==> 2
# 110 ==> 4 + 2 + 0 ==> 6
# 111 ==> 4 + 2 + 1 ==> 7
八进制结果为
	066267
1.4 原码,反码和补码【当小说看】

计算机之父冯·诺依曼

  • 二进制思想
  • 文件操作思想

冯·诺依曼提出原码,反码和补码来降低计算机的运算逻辑复杂度,要求所有的数据都采用补码形式参数。以整数为例讲解原码,反码和补码。

正整数 118 ==> 0111 0110(2),在计算机中正整数原码,反码和补码一致,在计算机中存储 118 对应的内存情况为

7 6 5 4 3 2 1 0
0 1 1 1 0 1 1 0

负整数 -118 补码数据需要进行一定的计算得到,有固定要求和格式

  • 原码:负整数的原码是对应正整数二进制数据为基准,最高位改为符号位 1

    118(10) ==> 0111 0110(2)
    # 取 118 正整数二进制使用,最高位改为 1 表示负数符号位
    -118(10) ==> 1111 0110(2)
    

    -118 原码为 1111 0110(2)

  • 反码: 原码除符号位之外,其他位置按位取反,0 变 1,1 变 0

    -118(10) ==> 1111 0110(2)
             反码:1000 1001(2)
    

    -118 反码为 1000 1001(2)

  • 补码: 反码 + 1

    -118(10) ==> 1000 1001(2)
    反码 + 1 ==> 1000 1001 + 1 ==> 1000 1010
    
  • -118 在内存中的存储形式为

7 6 5 4 3 2 1 0
1 0 0 0 1 0 1 0

计算机是利用反码形式完成相对应的数据计算,可以将 118 +(-118) 行为根据内存的数据内存内容进行分析得到

7 6 5 4 3 2 1 0
118 0 1 1 1 0 1 1 0
+ -118 1 0 0 0 1 0 1 0
0 1 0 0 0 0 0 0 0 0

2. 常量

2.1 常量概述

生活中不会发生改变的量都是常量,或者可以说开发中无法修改的数据是常量。

2.2 生活中的常量
  • 数值常量
    • 整数 10, 20, 30, 1, 2, 3, -1, -2, -3
    • 小数/浮点数 3.1415926 0.618 9.8
  • 文字/字符常量
    • 英文字符 A B C
    • 数字字符 1 2 3
    • 中文字符 你 我 他
  • 文本/字符串常量
    • "Break News: 湖人队浓眉交易独行侠东契奇"
    • "落霞与孤鹜齐飞,秋水共长天一色。渔舟唱晚,响穷彭蠡之滨;雁阵惊寒,声断衡阳之浦"
    • "先帝创业未半,而中道崩殂"
2.3 C/C++ 中常量要求

C/C++ 中基本常量类型有**【整数类型,浮点数据类型,字符类型和字符串类型】**

  • 整数类型:

    • 主要用于描述整数相关数值内容,数值常量

      10 20 30 
      1 2 3
      
  • 浮点类型

    • 用于描述小数/浮点数常量形式

      3.1415926 0.618 9.8
      
  • 字符类型

    • 【要求】在 C/C++ 中字符类型常量,要求使用英文单引号包含的单个元素

    • C/C++ 字符常量不支持中文,仅支持 ASCII 码(英文字母,数字字符,标点符号,特殊符号)

      'A' 'B' 'C'
      '1' '2' '3'
      
  • 字符串常量

    • 【要求】在 C/C++ 中字符串常量,使用英文双引号包含的所有内容

    • 虽然字符串支持中文,但是在实际开发中,中文出现的情况较少

      "Input Parameter is invalid!"
      "北国风光,千里冰封,万里雪飘..."
      
2.4 常量代码演示
2.4.1 代码实现
/* 
 * 在当前的程序中导入 stdio.h 头文件
 * 导入之后可以使用对应头文件中的相关资源,函数和功能
 */
#include <stdio.h>

/*
 * argc argument count 参数个数
 * argv argument value 参数数据
 */
int main(int argc, const char *argv[])
{
	/*
	 * 常量有 
	 *	整数常量,浮点数常量,字符常量,字符串常量
	 */
	printf("整数常量: %d\n", 2);
	printf("整数常量: %d\n", 7);
	printf("整数常量: %d\n", 3);

	printf("浮点常量: %f\n", 3.5);
	printf("浮点常量: %f\n", 4.5);

	printf("字符常量: %c\n", 'A');
	printf("字符常量: %c\n", '1');
	printf("字符常量: %c\n", '!');
	printf("字符常量: %c\n", '中');

	printf("字符串常量: %s\n", "Input Parameter is Invalid!");
	printf("字符串常量: %s\n", "哪吒票房92亿");

	return 0;
}
2.4.2 编译执行目标 C 语言程序
  • 编译,将 C 语言源文件编译满足当前系统环境下, CPU 可以识别的二进制可执行文件。

    • 编译操作格式

      qf@qf:~/桌面/Code/Day02$ gcc 01-第一行代码和常量.c 
      # gcc 是 C 语言编译工具
      # gcc C语言源文件
      
    • 编译完成之后可以得到默认文件名称为 a.out 可执行文件

      qf@qf:~/桌面/Code/Day02$ ls -l
      总用量 16
      -rw-rw-r-- 1 qf qf 1236 2月  12 14:35 01-第一行代码和常量.c
      -rwxrwxr-x 1 qf qf 8328 2月  12 14:39 a.out
      
  • 执行目标二进制可执行文件,CPU 执行目标程序。

    • 目标执行对应的 a.out 可执行二进制文件,格式

      qf@qf:~/桌面/Code/Day02$ ./a.out
      # . 表示当前工作目录
      # ./ 告知计算机,执行目标可执行文件
      
2.5 字符数据
2.5.1 字符集

对于计算机而言,每一个文字都是一个图片,在真实的程序中,文字对应的都是一个唯一的编码,计算机根据编码以及当前默认使用的字符集,展示对应的文字图片。开发中常用,常见的字符集

  • ASCII : 嵌入式开发中使用最多的编码,内容是英文字母大小写,数字字符,标点符号,特殊字符,任何一个可以在计算机中使用的字符集,必须支持 ASCII
  • GBK:中国国标,主要包括中文简体字和少数民族文字
  • UTF-8:万国码,后续开发中如果涉及到国际化开发,需要使用 UTF-8
  • BIG5:中文繁体字编码,主要用于中国台湾,中国香港,中国澳门
2.5.2 ASCII 内容使用要求
  • 在开发中使用任何字符数据,请使用字符本身,不允许使用对应编码值。会导致代码阅读性极差,需要严格遵守【数据类型一致化原则】
  • ASCII 码中编码 0 ~ 31 是不可见字符,对应的是键盘或者特殊用途符号,重点是编号为 0 的字符,nul
  • 数字字符在 ASCII 码中对应的顺序是 '0' ~ '9'
  • 英文字符,大写字母的编码值小于小写字母
  • 英文字符在 ASCII 大小写之间非连续存在,大写 'Z' 到小写 'a' 之间有其他字符。

2.5.3 转义字符【了解】
  • 本身基本特定含义的字符转换为无意义状态/仅字符状态,常用有
    • 双引号转义操作
    • 单引号转义操作
    • 转义标记字符转义操作
  • 特定字符使用转义操作,转换之后带有特定含义
    • \n 换行
    • \r 回车
      • 要求文本数据传输过程中,要求结尾必须是 \n\r or \r\n ,End Of File
    • \t 制表符 tab 键

3. 变量【小重点】

3.1 变量的概念

一杯水就是一个变量,水的容量会根据情况发生改变

  • 存在约定俗成的名称
  • 变量本身是一个容器,存储的数据是一个变化的内容
  • 不同的容量,不同的单位,支持的数据范围不同。
3.2 变量分类

基本数据类型变量分类和常量分类一致

  • 整数类型
  • 浮点数类型
  • 字符类型
3.3 变量的定义格式
数据类型 变量名 = 初始化数据;
  • 数据类型:明确约束当前变量可以存储的数据类型,有且只允许存储对应类型数据,请严格遵守【数据类型一致化要求】
  • 变量名: 【约定俗成,见名知意】,全英文。操作使用当前变量的名称,具备一定范围的唯一性。
  • = : 赋值号,将赋值号右侧的数据赋值给左侧的变量
  • 初始化数据:针对于当前变量数据类型,和业务场景所需的必要初始值。后续开发中任何一个变量必须在定义之后,进行初始化操作,避免【野值】问题。
3.4 基本数据类型
3.4.1 整数类型
  • 在 C/C++ 中整数类型计算机默认为 int 类型/标准整型,除非当前整数类型超出 int 存储范围,会自动选择采用 long 类型
  • int 数据类型在 32 位机及其以上占用内存字节数为 4 个字节,如果是 16 位机占用 2 个字节,8 位机占用 1 字节。
  • long 数据类型在 64 位机可以使用,占用内存为 8 个字节,如果是 32 位机占用 4 个字节
  • 后续开发中使用到芯片有 STM32 GD32 ESP32,可以认为 long 类型在以上芯片中都是 int 类型,还会使用到 ARM 相关芯片 RK3399 RK3588,ARM芯片都是 64 机,支持 long 类型
数据类型 占用内存字节数 存储数据范围
short 2字节(16bit) 0 ~ 65535 or -32768 ~ 32767
int 4字节(32bit) 0 ~ 2^32 - 1 or -2^31 ~ 2^31 - 1
long 8字节(64bit) 0 ~ 2^64 - 1 or -2^63 ~ 2^63 - 1

面试题: 请问 int 类型占用多少个字节

int 类型在 32 位机及其以上,占用 4 个字节,如果是 16 位机占用 2 个字节,8 位机占用 1 字节
#include <stdio.h>

int main(int argc, const char *argv[])
{
	// 数据类型 变量名 = 初始化数据; 
	// n ==> num ==> number
	short n1 = 10;
	int n2 = 100;
	long n3 = 10000;

	printf("n1 = %d\n", n1);
	printf("n2 = %d\n", n2);
	printf("n3 = %ld\n", n3);

	return 0;
}