extern
有两个作用:
- 当它与
"C"
一起连用。如:extern "C" void fun(int a);
这个高速编译器在编译fun这个函数名时安C的规则去翻译相应的函数名,而不是C++,因为C++在翻译的时候会把这个fun
名字变得面目全非,以支持C++的函数重载。 - 当
extern
直接放在变量名前和函数名前时。它可以使得你再多个模块之间共享该变量或者该函数,即你在一个模块中定义它,并在其他模块中使用extern
,因为它没有使用头文件,所以清楚地表明它只在少数模块之间共享。
在编译的过程中编译器只需要知道数据类型和名字,以便知道如何使用它所以不会报错。一旦编译完成后,链接器会针对模块source2
该extern
变量去所包含的模块source1
中生成的目标代码.obj
中找到此变量。即extern关键字是在链接阶段起作用.
header:
#ifndef HEADER_H
#define HEADER_H
extern int global_x;
void print_global_x();
#enif
source 1:
#include "header.h"
//it needs to be defined somewhere
int global_x;
int main()
{
global_x =5;
print_global_x(); // 5
return 0;
}
source 2:
#include <iostream>
#include "header.h"
void print_global_x()
{
//print global_x here;
std::cout<<global_x<<std::endl;
}
static 与extern
(static 表示静态变量,分配内存的时候存储在静态区)
1. static变量作用域只能是本身的编译单元,它的全局只对本编译单元有效,其他编译单元则看不到它。而extern变量通过extern可以使得其它编译单元引用使用该变量。
2. extern和static不能同时修饰一个变量。
header:
#ifndef HEADER_H
#define HEADER_H
static int static_x =2;
void print_static_x();
#endif
source1:
#include "header.h"
#include <iostream>
int main()
{
print_static_x(); //2
static_x =5;
print_static_x(); //2
std::cout<<static_x<<std::endl; //5
return 0;
}
source2:
#include "header.h"
#include <iostream>
void print_static_x()
{
std::cout<<static_x<<std::endl;
}
由于static变量只指针自身编译单元,所以以上两个编译单元中的static_x地址并不相同,正是因为static有以上的特性,所以一般定义static全局变量时,都把它放在原文件中而不是头文件,这样就不会给其他模块造成不必要的信息污染。
此外: C++中const修饰的全局常量据有跟static相同的特性,即它们只能作用于本编译模块中,但是const可以与extern连用来声明该常量可以作用于其他编译模块中.
volatile
确保编译器不会帮你对volatile
进行优化,让一切判断如你预期的执行。
int some_int = 100;
while(some_int == 100)
{
//your code
}
编译器可以优化此代码,因为它发现程序在此没有改变过some_int
于是将while(some_int ==100)
优化为while(true)
, 然而,有时这个值可能是通过外面某种方式改变,而编译器无法观察到。因此,为了确保获得所需的结果,您需要以某种方式阻止编译器优化while循环。这就是volatile关键字的作用。
volatile int some_int =100;
即volatile关键字是在编译阶段起作用.