static用法:
在C中,static主要定义全局静态变量、定义局部静态变量、定义静态函数。
1、定义全局静态变量:在全局变量前面加上关键字static,该全局变量变成了全局静态变量。全局静态变量有以下特点。
a.在全局区分配内存。
b.如果没有初始化,其默认值为0.
c.该变量在本文件内从定义开始到文件结束可见。
2、定义局部静态变量:在局部变量前面加上关键字static,其特点如下:
a.该变量在全局数据区分配内存。
b.它始终驻留在全局数据区,直到程序运行结束。
c. 其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。
3、定义静态函数:在函数返回类型前加上static关键字,函数即被定义为静态函数,其特点如下:
a.静态函数只能在本源文件中使用
b.在文件作用域中声明的inline函数默认为static类型
总结:用static定义的全局和局部静态变量的区别是,全局的静态变量的作用域和可见域都是从文件的定义开始到整个文件结束;而局部的静态变量可见域是从文件的定义开始到整个文件结束,作用域是从该语句块的定义开始到该语句块结束
extern的用法:
1、声明一个全局(外部)变量
当用extern声明一个全局变量的时候,首先应明确一点:extern的作用范围是整个工程,也就是说当我们在.h文件中写了extern int a;链接的时候链接器会去其他的.c文件中找有没有int a的定义,如果没有,链接报错;当extern int a;写在.c文件中时,链接器会在这个.c文件该声明语句之后找有没有int a的定义,然后去其他的.cpp文件中找,如果都找不到,链接报错。值得注意的一点:当extern语句出现在头文件中时,不要将声明和定义在一条语句中给出,也就是不要在头文件中写类似于这样的语句:
extern int a = 1;这种写法,在gcc编译时会给出一个警告:warning: 'a' initialized and declared 'extern'
注意:external声明和定义的区别,定义只有一次,但是声明没有限制
int a; --->定义,默认为0(等效于int a = 0;)
extern int a; --->声明外部变量
extern int a = 1; --->定义性声明(即在定义的同时声明为全局变量),一般不提倡
比如:
头文件a.h:
extern int a = 1;
头文件b.h:
#include "a.h"
......
源文件test.c:
#include "a.h"
#include "b.h"
......
这样肯定会报错:会报错说变量a重复定义
所有一般(提倡)的做法是:
只在头文件中通过extern给出全局变量的声明(即external int a; 而不要写成external int a = 1;),并在源文件中给出定义(并且只能定义一次)
比如:
头文件a.h:
......
源文件1.c:
#include "a.h"
int a = 0; --->定义
头文件b.h:
extern int a; --->声明
源文件2.c:
#include <stdio.h>
#include "2.h"
void print()
{
printf("a = %d\n", a);
}
源文件main.c
#include "1.h"
#include "2.h"
int main()
{
print();
return 0;
}
2、extern “C” { /*用C实现的内容(通常写在另外的.c文件中)*/ }
C++完全兼容C,当extern与“C”连用时,作用是告诉编译器用C的编译规则去解析extern “C”后面的内容。最常见的差别就是C++支持函数重载,而标准C是不支持的。如果不指明extern “C”,C++编译器会根据自己的规则在编译函数时为函数名加上特定的后缀以区别不同的重载版本,而如果是按C的标准来编译的话,则不需要。
static和external定义的全局变量区别:
注意:用static定义的全局静态变量可以被模块内所有的函数访问,但不能被模块外其他函数访问。而用external定义的全局
1、static修饰全局变量时,声明和定义是同时给出的;而extern一般是定义和声明分开,且定义只能一次
2、static的全局作用域只是自身编译单元(即一个.c文件以及这个.c文件所包含的.h文件);而extern的全局作用域是整个工程(一个工程可以包含很多个.h和.c文件)。即区别就在于“全局”的范围是整个工程,还是自身编译单元。