extern譯爲“外面的,外部的”,在C語言中用來聲明一個變量爲外部變量,也叫全局變量;或者聲明一個函數在外部進行了定義。也就是說,用extern修飾的變量或函數在同一工程下的其他文件也可以進行調用。
下面用具體的例子說明extern的用法。
1.extern對變量的聲明
假設在test.c文件中定義了一個變量a,如果在mian.c文件中想調用它,那麼有三種方式:①將變量a在test.h頭文件中聲明爲全局變量;②在main.c文件中調用變量a之前將a聲明爲全局變量;③變量a在test.c定義時直接聲明爲全局變量。
1.1在頭文件中聲明爲全局變量
test.h
#ifndef __TEST_H__
#define __TEST_H__
extern a;//聲明變量在外部進行了定義
#endif
test.c
#include <stdio.h>
#include "test.h"
int a=10;//定義變量,並進行賦值
mian.c
#include <stdio.h>
#include "test.h"//一定要包含頭文件纔可以使用全局變量a
int main()
{
printf("a=%d \r\n",a);//在test.c中定義過,並賦值爲10,此處應該輸出10
a=20;
printf("a=%d \r\n",a);//重新賦值,應該輸出20
}
輸出結果:
1.2在main.c文件中調用變量a之前將a聲明爲全局變量
test.c
#include <stdio.h>
//#include "test.h"//將.h文件屏蔽掉
int a=10;//定義變量,並進行賦值
mian.c
#include <stdio.h>
//#include "test.h"//屏蔽掉頭文件
extern int a;//聲明外部變量
int main()
{
printf("a=%d \r\n",a);//在test.c中定義過,並賦值爲10,此處應該輸出10
a=20;
printf("a=%d \r\n",a);//重新賦值,應該輸出20
}
輸出結果:
兩種方法從結果看都對,事實上,兩種方法本質是一樣的,第一種main.c包含了test.h頭文件,而test.h頭文件中進行了外部聲明,也就相當於間接在main.c中進行了外部聲明;第二種直接在main.c中進行了聲明。
1.3定義時直接聲明爲全局變量
test.c
#include <stdio.h>
//#include "test.h"//將.h文件屏蔽掉
extern int a=10;//定義變量,並進行賦值,並聲明爲全局變量
mian.c
#include <stdio.h>
//#include "test.h"//屏蔽掉頭文件
//extern int a;//屏蔽掉,不做外部聲明
int main()
{
printf("a=%d \r\n",a);//在test.c中定義過,並賦值爲10,此處應該輸出10
a=20;
printf("a=%d \r\n",a);//重新賦值,應該輸出20
}
輸出結果:
以上三種方式都可以正確定義聲明一個全局變量。但是注意,①像第3中方法這種定義時直接聲明的情況只能用在.c文件中,不能用在.h頭文件中,否則編譯會報錯;②不可以只在.h頭文件聲明外部變量,而在外部.c文件中不對變量進行定義,這樣也會報錯;③不可以在.h頭文件中進行定義變量,.h頭文件只能進行聲明。
2.extern對函數的聲明
假設在test.c文件中定義了一個求和函數sum(int a,int b),如果在mian.c文件中想調用它,那麼有兩種方式:①將求和函數sum(int a,int b)在test.h頭文件中聲明爲全局變量;②在main.c文件中調用求和函數sum(int a,int b)之前將求和函數sum(int a,int b)聲明爲全局變量;③求和函數sum(int a,int b)在test.c定義時直接聲明爲全局變量。
2.1在頭文件中聲明爲全局函數
test.h
#ifndef __TEST_H__
#define __TEST_H__
extern int sum(int a,int b);//聲明函數在外部進行了定義
#endif
test.c
#include <stdio.h>
#include "test.h"
int sum(int a,int b)//求和函數,返回a+b之和
{
return a+b;
}
mian.c
#include <stdio.h>
#include "test.h"//加載頭文件
int main()
{
int c;
c=sum(10,20);//求和
printf("c=%d \r\n",c);//應該輸出30
}
輸出結果:
事實上,在.h文件中聲明函數時,不用加extern也行,只要調用此函數的.c文件包含test.h頭文件即可。
2.2在.c文件中調用之前將函數聲明爲全局函數
test.c
#include <stdio.h>
//#include "test.h"//將.h文件屏蔽掉
int sum(int a,int b)
{
return a+b;
}
main.c
#include <stdio.h>
//#include "test.h"//屏蔽掉頭文件
extern int sum(int a,int b);//在調用之前聲明外部函數
int main()
{
int c;
c=sum(10,20);//求和
printf("c=%d \r\n",c);//應該輸出30
}
輸出結果:
2.3定義時直接聲明爲全局變量
test.c
#include <stdio.h>
//#include "test.h"//將.h文件屏蔽掉
extern int sum(int a,int b)//直接聲明爲外部函數
{
return a+b;
}
mian.c
#include <stdio.h>
//#include "test.h"//屏蔽掉頭文件
int main()
{
int c;
c=sum(10,20);//求和
printf("c=%d \r\n",c);//應該輸出30
}
輸出結果:
以上三種方法可以正確聲明定義一個外部函數。事實上,我在使用VS2010編譯時,在test.c文件中對求和函數不用extern進行外部聲明,在test.h文件中也不做聲明,也是可以編譯運行成功的,但是會出現警告,如下圖:
總結:
爲了避免可能的錯誤,大家還是規範些代碼比較好。一般對於全局變量和函數採用1.1和2.1的方式,這樣代碼層次清晰,方便理解和調試。
歡迎大家在評論區討論。