全局变量的使用

282 阅读2分钟
$ tree
.
├── head.cpp
├── head.h
└── main.cpp

0 directories, 3 files
// head.h
#ifndef __HEAD_H__
#define __HEAD_H__

int global_num;
int func();

#endif

// head.cpp
#include <stdio.h>
#include "head.h"

int func(){
  global_num = 10;
  printf("head func, %d %p\r\n",global_num,&global_num);
}


// main.cpp
#include <stdio.h>
#include "head.h"

int main(int argc, char const *argv[])
{
  global_num = 100;
  func();
  printf("main : %d %p \r\n",global_num,&global_num);
  return 0;
}

测试结果:

$ g++ *.cpp
/tmp/ccpCgEuI.o:(.bss+0x0): `global_num'被多次定义
/tmp/ccFO725K.o:(.bss+0x0):第一次在此定义
collect2: error: ld returned 1 exit status

but why ?

提示 全局变量 global_num 重复定义 !!!

static-test

尝试添加 static 关键字 :

// head.h
#ifndef __HEAD_H__
#define __HEAD_H__

// int global_num;
static int global_num;
int func();

#endif

// head.cpp
#include <stdio.h>
#include "head.h"

int func(){
  global_num = 10;
  printf("head func, %d %p\r\n",global_num,&global_num);
}


// main.cpp
#include <stdio.h>
#include "head.h"

int main(int argc, char const *argv[])
{
  global_num = 100;
  func();
  printf("main : %d %p \r\n",global_num,&global_num);
  return 0;
}

$ g++ *.cpp
$ ./a.out 
head func: 10  0x55d54c106014
main     : 100 0x55d54c106018 

发现两个 global_num 变量的地址已经不是同一个了 !

为什么在 head.h 中声明的一个 global_num 变量, 最终在多个 cpp 文件中 include 之后就变成了多个呢 ??

method-1

尝试使用 extern 关键字 :

// head.h
#ifndef __HEAD_H__
#define __HEAD_H__

// int global_num;
// static int global_num;

int func();

#endif

// head.cpp
#include <stdio.h>
#include "head.h"

// 在这里定义变量 global_num
int global_num;

int func(){
  global_num = 10;
  printf("head func, %d %p\r\n",global_num,&global_num);
}


// main.cpp
#include <stdio.h>
#include "head.h"

// 在其他需要用到该变量的地方使用 extern
extern int global_num;

int main(int argc, char const *argv[])
{
  int global_num = 0;    // 局部变量在函数内部会被同名全局遍历覆盖
  global_num = 100;
  func();
  printf("main : %d %p \r\n",global_num,&global_num);
  return 0;
}
$ g++ *.cpp
$ ./a.out 
head func : 10 0x561a83693014
main : 100 0x7fffdad6b394 

发现这个时候的 global_num 确实是多个文件都可以访问到的全局变量了 !


method-2

extern 修饰全局变量的另一种用法 :

在 xxx.h 中 extern int global_num; 然后在其他的 cpp 中 #include "xxx.h" 就可以了 int func(); 其实就是等价于 extern int func();
在头文件中修饰函数的时候,extern关键字可省略 但是这种方法存在一个问题 :

// head.h
#ifndef __HEAD_H__
#define __HEAD_H__

// int global_num;
// static int global_num;
extern int global_num;
int func();
#endif

// head.cpp
#include <stdio.h>
#include "head.h"

// 在这里定义变量 global_num
int global_num;
int func(){
  global_num = 10;
  printf("head func : %d %p\r\n",global_num,&global_num);
}


// main.cpp
#include <stdio.h>
#include "head.h"    // 直接 include 即可引用到 extern 全局变量

// 在其他需要用到该变量的地方使用 extern
// extern int global_num;

int main(int argc, char const *argv[])
{
  int global_num = 0;    // 局部变量在函数内部会被同名全局遍历覆盖
  global_num = 100;
  func();
  printf("main      : %d %p \r\n",global_num,&global_num);
  return 0;
}

test:

$ g++ *.cpp head.h 
$ ./a.out 
head func : 10 0x55f31800b014
main      : 100 0x7ffcf71d8e74 

可以看出两个 global_num 的地址是不一样的, 原因是 main 中的局部变量 int global_num=0; 的地址, 可 为什么同名的局部变量没有被全局变量覆盖掉呢 ?


总结

所以:
建议使用 :

// demo.cpp
extern int a = 100;
// 等价于 int a = 100;
// 因为现在编译器默认源文件中的全局变量可以被其他源文件引用
// test.cpp
// 引用 demo.cpp 中的全局变量 a
extern a;