简要说下extern:
extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。
C/C++中extern关键字详解
- extern 和 static
上文对extern 和 static做了说明,并举了例子,我对其进行了测试:
test1.h
#ifndef TEST1H
#define TEST1H
static char g_str[] = "123456";
extern char g_char;
void fun1();
#endif
test1.cpp
#include "test1.h"
#include <iostream>
using namespace std;
char g_char = 'W';
static char s_char = 'H';
void fun1() {
cout << g_str << endl;
cout << g_char << endl;
cout << s_char << endl;
}
test2.cpp
#include "test1.h"
#include <iostream>
using namespace std;
void fun2() {
cout << g_str << endl;//g_str(static修饰)在内存中有多份
//extern g_char;
cout << g_char << endl;//g_char(extern 修饰)在内存中只有一份0x601077
//cout << s_char << endl;
}
int main() {
fun1();
fun2();
return 0;
}
gdb 调试
fun1 () at test1.cpp:7
7 cout << g_str << endl;
(gdb) p &g_str
$1 = (char (*)[7]) 0x601070 <g_str>
(gdb) n
123456
8 cout << g_char << endl;
(gdb) p &g_char
$2 = 0x601077 <g_char> "W123456"
(gdb) n
W
9 }
(gdb) n
main () at test2.cpp:14
14 fun2();
(gdb) s
fun2 () at test2.cpp:7
7 cout << g_str << endl;
(gdb) p &g_str
$3 = (char (*)[7]) 0x601078 <_ZL5g_str>
(gdb) n
123456
9 cout << g_char << endl;
(gdb) p &g_char
$4 = 0x601077 <g_char> "W123456"
可见,g_str(static修饰)在内存中有多份,g_char(extern修饰)在内存中只有一份0x601077。 我们通常说static修饰的全局变量只能在一个文件中使用,而不能在其他文件中使用,而在此例中,发现g_str在内存中有多份,这是因为在Test2.cpp中include “test1.h”,所以相当于test2.cpp也定义了一个g_str,但两者却是不同的,即使存储的内容相同但地址不同。下面举一个例子说明“static修饰的全局变量只能在一个文件中使用,而不能在其他文件中使用”:
test1.cpp
#include <iostream>
using namespace std;
char s_char = 'H';
void fun1() {
cout << s_char << endl;
}
test2.cpp
#include <iostream>
//#include "test1.cpp""
using namespace std;
extern char s_char; // 声明s_char在其他文件中定义
void fun2() {
cout << s_char << endl;
}
int main() {
//fun1();
fun2();
return 0;
}
此时g++ -g –std=c++11 -o test test2.cpp test1.cpp 可以编译通过运行成功。
但若在test1,cpp中加入static,如:
test1.cpp
#include <iostream>
using namespace std;
static char s_char = 'H';
void fun1() {
cout << s_char << endl;
}
则编译出错:对‘s_char’未定义的引用
collect2: error: ld returned 1 exit status
C/C++中extern关键字详解 中对于static不存在重复定义的问题,而对于extern char g_str[]=”123456”那种情况却存在重复定义,原因在于:static修饰全局变量的作用域只能是本身的编译单元,即本文件中。 所以即使test1.cpp 和 test2.cpp中都定义了static全局变量,但它们仅限于本文件中; 而extern char g_str[]= “123456”; // 这个时候相当于没有extern, 这个全局变量就不限于本身编译单元,所以会出现重复定义的错误
最后,作者给了点建议:1 一般定义static全局变量时,都把它放在原文件中而不是头文件; 2 只在头文件中尽量做声明,比如extern char g_str[]