extern 与 static
修饰符 | 意义 |
---|---|
extern | 变量/函数定义位于其他文件中 |
<空> | 变量/函数定义于本文件(公用)且可以用于其他文件 |
static | 变量/函数对此文件来说是局部(专用) |
static有两重意思。
- 对于全局定义的数据来说,它意味着”对此文件专用“。
- 对在一个函数中定义的数据来说,它是指”从静态内存(而不是从临时堆栈)分配的变量。
场景一
main.c
extern int flag; // 此处仅是声明变量,所以不能初始化
int main()
{
printf("%d", flag);
}
sub.c
int flag = 1;
如果在main.c中extern int flag = 1
,则编译时会出现如下信息:
main.c:5:12: warning: ‘flag’ initialized and declared ‘extern’
extern int flag=1;
^~~~
/tmp/cc7rJpMh.o:(.data+0x0): `flag'被多次定义
/tmp/ccCtPSdg.o:(.data+0x0):第一次在此定义
collect2: error: ld returned 1 exit status
场景二
下面两个文件中的静态变量只在其所在文件中生效,所以不存在冲突
main.c
static int flag = 4;
int main()
{
printf("%d", flag);
}
sub.c
static int flag = 6;
extern 对比 inlcude头文件
头文件
模块间共享的信息应该放在头文件中。如:
- 清楚地描述模块做什么,以及能为用户提供什么功能的注释
- 一般常量
- 一般结构
- 所有共用函数原型
- 公用变量的extern定义
使用extern还是include头文件?
- 使用include将另一个文件全部包含进去,可以引用另一个文件中所有全局变量和全局方法,存在风险。
- 如果只是希望使用另一个文件中的某个变量或方法,则使用extern关键字更好。
例子
希望在头文件中定义一个全局变量,然后包含到两个不同的c文件中,希望这个全局变量能在两个文件中共用。测试代码如下:
// main.c
#include <stdio.h>
#include "common.h"
int main()
{
printf("main.c : %d", key);
return 0;
}
// common.c
#include "common.h"
void test_f()
{
printf("common.c : %d", key);
}
// common.h
#ifndef _COMMON_H_
#define _COMMON_H_
int key = 1;
#endif
结果
- 编译的时候编译器提示出错,一般提示大概都类似于:Symbol key multiply defined 。也就是说重复定义了key这个变量。这是因为#include命令就是原封不同的把头文件中的内容搬到#include的位置,所以相当于main.c和common.c中都执行了一次int key,而C语言中全局变量是项目内(或者叫工程内)可见的,这样就造成了一个项目中两个变量key,编译器就认为是重复定义。
- common.h 中的#ifndef、#define、#endif 的目的避免出现同一个文件中多次包含文件common.h,不能避免重复定义全局变量。
解决办法
使用extern关键字来声明变量为外部变量。在main.c中extern关键字声明变量key为外部变量。
注意:在common.c中由于使用include "common.h",则无需使用extern声明变量key。
总结:变量key在整个工程中只在common.h中被定义一次。
// main.c
#include <stdio.h>
extern int key;
extern void test_f();
int main()
{
printf("main.c : %d\n", key);
test_f();
return 0;
}
// common.c
#include "common.h"
void test_f()
{
printf("common.c : %d", key);
}
// common.h
#ifndef _COMMON_H_
#define _COMMON_H_
int key = 1;
#endif
参考文献
- 《实用C语言编程》2000.05 电力出版社,P356
- C语言中extern用法详解
- C语言正确使用extern关键字
generated by haroopad