Appearance
头文件剖析
基本概念
在一个C文件中除了main、跳转标号不需要声明之外所有的标识符在使用之前都需要进行声明,一般我们把函数的声明放在头文件中。
变量声明 != 变量定义 ===> 区别:是否分配内存
变量定义:生成相关的汇编指令
变量声明:告诉编译器,有可能存在于别的文件,编译时候先不要报错,在连接的时候到相应的文件中查找,没有 再报错
定义只有一次,声明可以有多次
C
1 #include <stdio.h>
2
3 #ifndef __LCD_H__
4 #define __LCD_H__
5
6 #define PI 3.14
7 void lcd_init(void);
8 #endif
注:
- 如果在头文件定义了新的数据类型,宏定义,就需要包含条件编译防止多次包含
隐式声明
==如果没有进行声明只产生一个警告,不会报错,并且增加一个隐式声明==
给出的隐式声明可能会与原函数的数据格式有区别,造成错误
变量声明与定义
extern:使用文件外的参数
C
//1.c
1 int i = 0;
2 int a[10] = {1, 2, 3, 4, 5,6 ,7 ,8 ,9 , 0};
3 struct student
4 {
5 int age;
6 int num;
7 };
8 struct student stu = {20, 1001};
9 int k;
10
//main.c
1 #include <stdio.h>
2
3 extern int i;
4 extern int a[10];
5 struct student{
6 int age;
7 int num;
8 };
9 extern struct student stu;
10 extern int k;
11
12 int main(void)
13 {
14 printf("%s: i = %d\n", __func__, i);
15 for(int j = 0; j<10 ; j++)
16 printf("s[%d]: %d\n", j, a[j]);
17 printf("stu.age = %d, num = %d\n", stu.age, stu.num);
18 printf("%s: k = %d\n", __func__, k);
19 return 0;
20
21 }
result:
main: i = 0
s[0]: 1
s[1]: 2
s[2]: 3
s[3]: 4
s[4]: 5
s[5]: 6
s[6]: 7
s[7]: 8
s[8]: 9
s[9]: 0
stu.age = 20, num = 1001
main: k = 0
- 使用了extern无初始化语句则为声明
- 没有使用extern无初始化语句则为试探性定义
- 没有使用extern有初始化语句则为定义
试探性定义:该变量可能在别的文件中有声明,如果没有按照规则声明并初始化默认值:NULL, 0,
undefined value等 。如果别的文件中有定义,那把他当成声明
产生原因
由于内存原因,早期的C语言一次只能编译一个文件,每个源文件单独编译,只编译一次
前向引用
没有声明就可以使用
- 隐式声明(新的标准中被禁用)
- 语句标号:跳转向后
- 不完全类型:被定义完整之前用于特定的用途
不完全类型
- void
- 一个不确定大小的种类
- 一个不确定的struct或者union
C
int array_print(int i[], int len);
struct LIST_NODE
{
struct LIST_NONE *next;//在定义结束前已经使用
int data;
};
goto error;
注:在进行对不完全类型的引用时候只能使用类型属性,其他的如变量值,结构成员,大小等不能使用
如果只是用指针就可以不用考虑这些
C
struct person;\\前向声明
struct student{
struct person *p;
int score;
int no;
};
模块的封装
add.h
C
int add(int a, int b);
add.c
- 包含自己的头文件:在编译时候进行检查,防止声明与定义不一致
C
#include "add.h"
int add(int a, int b)
{
return a+b;
}
main.c
C
#include <stdio.h>
#include "add.h"
int main(void)
{
int sum;
sum = add(1, 2);
return 0;
}
头文件路径
- <>:标准头文件,官方路径
- "":自定义的文件
可以使用gcc -I来指定目录
搜索顺序<>:
- gcc -I
- 环境变量指定
- GCC内定文件
搜索顺序"":
- 当前目录
- gcc -I
- 环境变量
- GCC内定文件
Linux常用的路径
PATH:可执行文件搜索
C_INCLUDE_PATH: C语言头文件搜索路径
CPLUS_INCLUDE_PATH: c++头文件路径
LIBRARY_PATH:库文件搜索路径
头文件中的内联函数
- 在多个模块调用这个文件的时候,内联函数已经被展开了,通常与static一同使用,确定作用域在本文件之中