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文件)。即區別就在於“全局”的范圍是整個工程,還是自身編譯單元。