static 关键词的使用
2.1 什么叫函数重复定义
我们经常会遇到报错,说变量或者函数重复定义。那么,在此,首先我举例说明一下什么叫函数的重复定义。
- //a.c文件
- void test()
- {
- return;
- }
- //b.c文件
- void test()
- {
- return;
- }
那么,在编译的时候是不会报错的,但是,在链接的时候,会出现报错:
multiple definition of `test',因为在同一个工程里面出现了两个test函数的定义。
用static修饰函数,则表明该函数只能在本文件中使用,因此,当不同的文件中有相同的函数名被static修饰时,不会产生重复定义的报错。例如:
- //a.c文件
- static void test()
- {
- return;
- }
- void test_a()
- {
- test();
- }
- //b.c文件
- static void test()
- {
- return;
- }
- void test_b()
- {
- test();
- }
编译工程时不会报错,但是test()函数只能被 a.c 和 b.c 中的函数调用,不能被 c.c 等其他文件中的函数调用。
那么,用static修饰 .h 文件中定义的函数,会有什么效果呢?
- //a.h文件
- static void test()
- {
- return;
- }
- //b.c文件
- #include "a.h"
- void test_b()
- {
- test();
- }
- //c.c文件
- #include "a.h"
- void test_c()
- {
- test();
- }
这样的话,在预编译后,b.c 和 c.c 文件中,由于 #include "a.h" ,故在这两个文件开头都会定义 static void test() 函数,因此,test_b() 和 test_c() 均调用的是自己文件中的 static void test() 函数 , 因此不会产生重复定义的报错。
因此,结论,在 .h 文件中定义函数的话,建议一定要加上 static 关键词修饰,这样,在被多个文件包含时,才不会产生重复定义的错误。
- //a.h文件
- static void test_a()
- {
- return;
- }
- //b.h文件
- #include "a.h"
- //c.h文件
- #include "a.h"
- //main.c文件
- #include "b.h"
- #include "c.h"
- void main()
- {
- test_a();
- }
这样就“不小心”产生问题了,因为 b.h 和 c.h 都包含了 a.h,那么,在预编译main.c 文件的时候,会展开为如下形式:
- //main.c 预编译之后的临时文件
- static void test_a()
- {
- return;
- }
- static void test_a()
- {
- return;
- }
- void main()
- {
- test_a();
- }
在同一个 .c 里面,出现了两次 test_a() 的定义,因此,会出现重复定义的报错。
但是,如果在 a.h 里面加上了 #ifndef……#define……#endif 的话,就不会出现这个问题了。
例如,上面的 a.h 改为:
- //a.h 文件
- #ifndef A_H
- #define A_H
- static void test_a()
- {
- return;
- }
- #endif
预编译展开main.c则会出现:
- //main.c 预编译后的临时文件
- #ifndef A_H
- #define A_H
- static void test_a()
- {
- return;
- }
- #endif
- #ifndef A_H
- #define A_H
- static void test_a()
- {
- return;
- }
- #endif
- void main()
- {
- test_a();
- }
在编译main.c时,当遇到第二个 #ifndef A_H ,由于前面已经定义过 A_H,故此段代码被跳过不编译,因此,不会产生重复定义的报错。这就是 #ifndef……#define……#endif 的精髓所在。