- day4
- 一、枚举
- 1.定义
- 用户自定义数据类型,可以用于声明一组常数。
- 以每周七天为例,我们可以使用#define命令来给每天指定一个名字:
- #define Mon 1
- #define Tues 2
- #define Wed 3
- #define Thurs 4
- #define Fri 5
- #define Sat 6
- #define Sun 7
- #define命令虽然能解决问题,但也带来了不小的副作用,导致宏名过多,代码松散,看起来总有点不舒服。C语言提供了一种枚举(Enum)类型,能够列出所有可能的取值,并给它们取一个名字。
- 2.格式
- enum 枚举名 { value1, value2, value3, ... };
- 未赋初值时,第一个常数会默认为0,依次加一。可以每个元素都赋值,如果有元素没有赋值则默认值为上一个元素的值加一。
- 二、数据类型总结
- 1.基本数据类型
- 基本数据类型最主要的特点是其值不可以再分解为其它类型。也就是说,基本数据类型是自我说明的。如char, short, int, long, float, double, signed, unsigned。
- 2.构造数据类型
- 构造数据类型是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说,一个构造类型的值可以分解成若干个“成员”或“元素”。每个“成员”都是一个基本数据类型或又是一个构造类型。如struct结构体、union联合体、enum枚举和数组。
- 3.指针类型
- 指针是一种特殊的数据类型。其值用来表示某个变量在内存中的地址。虽然指针变量的取值类似于整型量,但这是两个类型完全不同的量,因此不能混为一谈,定义时要用星号*。
- 4.空类型
- 空类型void用来定义任意类型的指针和无返回值的函数。
- 三、存储类型
- 1.存储类型:auto static extern register
- 1.1 auto
- 修饰变量,一般省略时会认为是auto类型。其特点是当执行流程进入该语句块的时候初始化可为任何表达式。
- auto 数据类型变量名/指针/数组;
- (auto) int a;
- 放在栈区。
- 1.2 static
- 可以修饰变量函数
- 1.2.1 修饰变量
- 1. 变量的存放位置在全局区(静态区) 如果静态变量有初值,存放.data区,没有初值存放在.bss区域
- 2. 生命周期为整个程序
- 3. 限制作用域: 修饰局部变量,和普通局部变量作用域没有区别,但是生命周期被延长为整个程序。 修饰全局变量,限制在本文件中使用。
- 4.只初始化一次,初值赋值0。
- 1.2.2 修饰函数
- static修饰函数,限制在本文件使用。 总的来说,使用 static 定义的变量存储在静态存储区(全局区)中,具有静态持续性,即使函数返回,它的值也会保留。而且,static 变量只能在当前文件中访问,不能被其他文件访问。
- 1.3 extern
- 外部引用: 通过extern可以引用其他文件的全局变量或者函数


- 注意:编译的时候要同时编译包含外部引用内容的文件
- 1.4 register寄存器类型
- register是寄存器类型,顾名思义,是把修饰的变量放到寄存器中,目的是为了提高程序的运行效率。但要记住,不管是单片机也好,计算机也罢,任何CPU的寄存器资源都是有限的,如果寄存器满了,被修饰的变量就会默认回到auto类型。
- 四、分文件编程
- 1.头文件: .h结尾的文件
- 函数声明、头文件、宏定义、typedef、结构体、共用体以及枚举的定义和外部引用。 全局变量一般不会放在头文件中。
- 2.源文件: .c结尾的文件
- 包含main函数的.c文件: main函数
- 包含子函数的.c文件: 子函数
- 五、编译工具
- 1.gcc 编译工具
- 预处理: 展开头文件,替换宏定义,删除注释,不会进行语法检查,处理#开头的语句。 gcc -E xx.c -o xx.i
- 编译: 检查语法错误,将.i文件转换成.s汇编文件。 gcc -S xx.i -o xx.s
- 汇编:将汇编文件生成二进制文件(不可执行) 。gcc -c xx.s -o xx.o
- 链接: 链接库文件,将不可执行的二进制文件转换成可执行的二进制文件。 gcc xx.o -o xx, gcc xx.c 默认生成a.out, gcc xx.c -o xx生成一个新名字的可执行文件。
- 2.gdb调试工具
- gcc -g xx.c 生成a.out
- gdb a.out
- r:运行代码
- l: 查看文件
- b 行号或者函数名:添加断点
- info b:查看断点情况
- d num(断点编号):删除断点
- p 变量名:查看变量的值
- s/n: 单步运行,s会进入子函数顺序执行;单步跳过,n不会进入子函数
- c: 执行到下一个断点的位置
- help:帮助
- q: 退出
- 步骤:代码写好后,先通过gcc -g进行编译代码,没有错误后,可以通过gdb a.out进行调试,输入l查看文件内容,通过b设置断点,输入r进行运行,n或s进行单步调试,q退出。
- 3.make工具
- 3.1 定义
- make:工程管理器,顾名思义,是指管理较多的文件。
- make工程管理器也就是个“自动编译管理器”,这里的“自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入Makefile文件文件的内容来执行大量的编译工作。
- Makefile或makefile时make读取的唯一配置文件。
- 3.2 Makefile格式
- 目标: 依赖 命令
- 注意:命令前面要用TAB键
- 理解:通俗一点讲就是 依赖(相当于原材料) -> 命令(加工)-> 目标(产物)
- makefile根据以下步骤写: gcc -c xx.c -o xx.o, gcc xx.o -o xx
- 使用make命令
- 目标加:是伪目标
- 伪目标:它的目的并不是创建目标文件(所以称作“伪”),而是想去执行这个目标下面的命令。

- 执行: make clean
- 规则中 rm 命令不是为了创建 clean 这个文件,而是执行删除某些文件的任务。当工作目录中不存在以 clean 命令的文件时,输入 make clean 命令,命令 rm *.o test会被执行。
- 如果避免同名文件可以加:.PHONY:clean
- 3.3 用make管理多个文件
- 先分文件编程test.c和add.c, 再建立makefile管理:

- 执行:make
- 清除中间文件:make clean
- .PHONY:clean 为了避免路径中出现同名文件

- 3.4 makefile变量
- 3.4.1 自定义变量
- 自己定义的变量: 一般用大写表示变量名, 取变量值用$(变量名)
- (1) = 递归方式展开
- (2):= 直接赋值(当前的值是什么就立即赋值)
- (3)+= 追加新的值
- (4)?= 判断之前是否定义,如果定义了,不重新赋值,否则赋值
- 3.4.2 预定义变量
- 系统预先定义好的一些变量,可能有默认值可能没有默认
- RM 文件删除程序的名称,默认值为rm -f
- CC C编译器的名称,默认值为cc。
- CPP C预编译器的名称,默认值为$(CC) –E。
- CFLAGS C编译器的选项,无默认值。
- OBJS 生成的二进制文件或目标文件,自己定义
- 3.4.3 自动变量
- $< 第一个依赖文件的名称
- $@ 目标文件的完整名称
- $^ 所有不重复的依赖文件,以空格分开
- 可以用%.c和%.o代替每一个.c和.o文件: 相当于让每个.c生成各自的.o
- 3.5 make指令


- make -s: 隐藏执行的命令
- make -C 路径:进入指定的路径去执行make指令