在编写源码过程中,随着功能的复杂,所使用的各种函数模块和其他相关的技术会迅速增加,如果所有的代码都放在源文件.c里面,会显得组织难以维护,互相引用非常 频繁,尤其是大家都要用到的部分内容(比如:函数声明,结构体模板,头文件引用。。。)最好能有一个统一的地方,专门用来存放这些东西。那么我任意一个源文件在需要用这些的时候直接从这里拿,这样可以优化工程项目的代码结构,也方便维护和升级
这个统一存放相应信息的地方就是头文件,以.h为文件名后缀
1其他头文件的引用
2宏定义
3结构体、联合体、枚举的声明
4全局变量
5静态函数或内敛函数定义
6普通函数的声明
普通函数的定义不能放在头文件中,假如这个头文件被多个.c引用,那么当他们在一起编译的时候,会出现函数重定义的错误
static函数和inline函数能定义在头文件里面,而且一般将static函数定义在头文件
由于头文件可以嵌套包含别的头文件,还有就是多个源文件可能包含同一个头文件,为了防止头文件被重复引用,头文件的书写格式是有一定要求的。
#ifndef _SHOP_H_ //如果没有定义_SHOP_H_宏
#define _SHOP_H_ //定义_SHOP_H_宏
//头文件正文
#endif //结束定义
#include
#include “shop.h”
<>:直接从标准库去寻找头文件
“”:先从当前工程目录去寻找头文件,如果没有找到就会去标准库路径查找相应的头文件
所以一般来说:要引用标准库头文件就用<>,引用自定义头文件就用””
编译命令:
gcc ./src/* -o ./bin/main -I ./include/
-I:表示指定头文件所在路径
相当于就是去编译你的整个工程的脚本
all:
gcc ./src/* -o ./bin/main -I ./include/
clean:
rm ./bin/main
在Makefile存放的路径下make
make clean:删除bin/main
什么是宏?
宏定义,就是一个标识符表示一串字符,可以是常量,表达式,可以带参数,如果后面的代码出现了该标识符,那么就全部替换成指定的这串字符
宏可以写在函数里面
预处理,编译,汇编,链接
gcc编译代码的时候,在预处理过程中,会将所有的宏进行替换,而替换过程中,不检查语法错误
#define 宏名 字串
#表示这里是一条预处理命令
宏名:是标识符的一种,命名规则和变量一样,一般用大写字母
字串:可以是数字,表达式,if语句,函数,字符串
1、由字母,数字,下划线组成
2、不能以数字开头
3、不能是C语言自带的关键字
宏定义用宏名来表示一个字串,在宏展开的时候,用这个字串来取代宏,这个是一种简单粗暴的替换(不会做任何的检查,也不做任何运算)
宏定义不是说明或语句,不能在末尾加分号
宏写在函数体外,作用域从定义开始到程序结束,终止宏定义作用域
在代码中宏被双引号包围,预处理过程中就不会对这个位置进行宏替换
宏定义语句允许嵌套
习惯上宏名一般全部大写,便于与普通变量区别
宏定义可以表示数据类型,但是一般不这么做
__DATE__ 预处理日期,格式”MM DD YYYY”的字符串
__TIME__ 预处理时间,格式”HH MM SS”的字符串
__FILE__ 当前文件名
__LINE__ 当前行号
__FUNCTION__ 当前函数
STDC 当编译器标准为ANSI的时候,值为1
语法:
#define 宏名(形参列表) 字串
带参宏不需要指定返回值类型和形参类型
带参宏定义中,宏名和形参列表之间不能有空格,参数列表之间是可以加空格的
在宏定义中,字串内的形参通常要用括号括起来,避免直接替换过程中由于没有考虑到运算符优先级问题,导致的逻辑错误
#define MAX(x, y) ((x)>(y)?(x):(y))
当宏在一个单行上如果太长,可以使用这个运算符把字串分行表示
#define MAXX(x, y) \
({\
int _a = x;\
int _b = y;\
((_a)>(_b)?(_a):(_b));\
})
int d = MAXX(10, 20);
宏可以用do…while(0)将宏的多条语句这种字串放在一起
#define MAXXX(x, y) do{\
int _a = x;\
int _b = y;\
((_a)>(_b)?(_a):(_b));\
}while(0)
需要注意:这种写法不带返回值
宏展开仅仅是字串的替换,不会进行任何的表达式计算
宏在编译之前(预处理)就被处理掉了,没有任何机会参与编译,不会占内存
函数是重复使用的代码,会被编译,每次调用函数是执行这块空间的代码,函数形参和局部变量都会分配内存
#define PRI(a, b) printf("%s and %s we are family\n", a, b)
#define PRIN(a, b) printf(#a " and " #b " we are family\n")
int main(int argc, char const *argv[])
{
PRI("xiaoming", "xiaohong");
PRIN(xiaoming, xiaohong);
printf("%s and %s we are family\n", "xiaoming", "xiaohong");
return 0;
}
#define PRINT(a) printf("n"#a " = %d\n", n##a)
int main(int argc, char const *argv[])
{
int n1 = 100;
PRINT(1);
return 0;
}
d %s we are family\n", “xiaoming”, “xiaohong”);
return 0;
}
###### 标记粘贴运算符 ##
```c
#define PRINT(a) printf("n"#a " = %d\n", n##a)
int main(int argc, char const *argv[])
{
int n1 = 100;
PRINT(1);
return 0;
}