一、变量的声明和定义

C++的分离编译机制允许程序拆分成多个文件来写,最常见的是在头文件中进行声明,源文件中进行定义,然后一起编译:

gcc a.h a.cpp -o a.o

声明使得函数或者变量被程序所知,定义负责创建与声明相关联的实体。变量只能被定义一次,但能多次声明。

声明变量的两种方式:

  • 使用extern关键字且没有被显示初始化,如extern int i;
  • 不使用extern关键字且没有被显示初始化,如int i;

一旦一个变量被显示初始化了,该条语句就会被认为是定义,例如extern double pi = 3.14;

二、声明和定义的必要性

声明和定义在多个文件中比较重要,特别是对于在多个文件中都要使用的同一个变量,必须进行声明。

例如三个文件test.h, test1.cpptest2.cpp中都要使用同一个全局变量的情况:

// test.h
extern int gCnt;  // 对全局变量gCnt进行声明
int f1();  // 声明函数f1(),可以不加extern
int f2();  // 声明函数f2()
// test1.cpp
int gCnt;  // 定义gCnt
int f1(){
    return gCnt;
}
// test2.cpp
#include"test.h"
// 无需再对gCnt进行定义
int f2(){
    return gCnt
}

main.cpp

#include<iostream>
#include"testa.h"
using namespace std;

int main() {
    cout << f1() << endl;
    cout << f2() << endl;
    return 0;
}

编译运行,程序输出:

0
0

test.h中声明变量gCnt,另外的两个文件中分别引用头文件,并且其中一个定义gCnt。由于变量只能被定义一次,所以不能同时在test1.cpptest2.cpp中定义gCnt,否则会报错:

/tmp/cc2lxN5u.o:(.bss+0x0): multiple definition of `gCnt''
/tmp/ccWKRQpn.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status

根据变量的默认初始化规则,test1.cpp中的全局变量gCnt会被默认初始化为0,就相当于执行了int gCnt=1;

值得注意的是,头文件中的extern关键字不能省,因为省略extern编译器会把它当作全局变量定义。然后被同时两个cpp文件包含,预处理阶段就会生成两个gCnt的定义,导致编译错误:

/tmp/cc1Y7L4l.o:(.bss+0x0): multiple definition of `gCnt''
/tmp/ccsAd6YS.o:(.bss+0x0): first defined here
/tmp/cc99tPeP.o:(.bss+0x0): multiple definition of `gCnt''
/tmp/ccsAd6YS.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

三、extern和static

extern和static

最后修改:2018 年 03 月 15 日
如果觉得我的文章对你有用,请随意赞赏