c/c++中extern關鍵字詳解


.h作用:

  頭文件.h用於編寫變量和函數的聲明,對用戶來說起到一個接口手冊和說明的作用。在編譯過程的預編譯階段,會將所有的#include原封不動的在原地展開。因此在利用makefile的make時候如果只是修改了.h頭文件,利用make編譯的時候不會進行增量編譯,因為.h對應的.cpp或者.c並沒有改變。需要單獨刪除.h對應的.o文件再進行make。

編譯過程:

編譯過程分為:

  1. 預編譯階段:作用:對源文件中的宏進行展開,對#include展開等等。命令:gcc -E test.c -o test.i
  2. 編譯:將展開后的源文件編譯成匯編文件(匯編語言)命令:gcc -S test.i -o test.s
  3. 匯編:將匯編文件編譯成01機器碼的.o文件  命令:as test.s -o test.o
  4. 鏈接:將所有的.o文件鏈接(鏈接引用庫等等)成一個可執行程序.exe文件。gcc test.o test2.o -o test

編譯過程示例:

//lib.h
int addTwo(int a, int b);

//lib.c
int addTwo(int a, int b)
{
    return a+b;
}
//main.c
#include <stdio.h>
#include "lib.h"
int main()
{
    int sum = addTwo(1, 2);
    printf("sum=%d\n", sum);  
    return 0;
}

gcc -E main.c -o main.i進行預編譯:

可以看到stdio.h展開了好幾百行到main.c文件中,lib.h將函數的聲明展開到了源文件中。

最后進行鏈接的命令是:

gcc main.o lib.o -o main

生成可執行程序。編譯命令中沒有.h文件,因為在預編譯過程中已經將所有的.h文件都展開到了源文件中了。

extern簡述:

  extern是計算機語言中的一個關鍵字,可置於變量或者函數前,以表示變量或者函數的定義在別的文件中。提示編譯器遇到此變量或函數時,在其它模塊中尋找其定義。

  每一個c文件或者cpp文件最后都會編譯為一個.o文件或者.obj文件,最后將所有的.o或.obj文件鏈接起來組成一個可執行.exe文件。在其他模塊的意思是指在鏈接的時候從其他.o或者.obj文件中找extern變量的定義。

extern代碼示例:

對變量而言,如果你想在本源文件(例如文件名A)中使用另一個源文件(例如文件名lib)的全局變量(假設為int gVar),方法有2種:

一、在文件A中聲明extern int gVar,且不包含lib的全局變量gVar。表示編譯器在鏈接的時候在另外模塊中尋找gVar的定義。即在lib.o中尋找。

//lib.h
int gVar = 3;

//lib.c
#include "lib.h"
//A.c
int main()
{
    extern int gVar;
    printf("gVar=%d\n", gVar);
}

程序正常輸出3;

編譯鏈接的時候需要將lib.o加上:gcc main.c lib.c -o main

 

二、在lib.h文件中聲明全局變量extern int gVar,在lib.c中定義變量gVar。文件A中包含這個lib.h,即可直接使用gVar變量了。

考慮下面這種情況:

//lib.h
int gVar=3;
int addTwo(int a, int b);

//lib.c
#include "lib.h"
int addTwo(int a, int b)
{
    return a+b;
}
//A.h
#include "lib.h"

//A.c
#include "A.h"

int main()
{
    int sum = addTwo(1,2);
    printf("sum=%d\n", sum);
    printf("%d\n", gVar);
    return 0;
}

當進行gcc lib.c A.c -o A的時候會報錯。

原因是在鏈接的過程中發現重復定義了變量gVar:

修改如下:

//lib.h
extern int gVar;  //聲明全局變量 extern int gVar = 3;是定義
int addTwo(int a, int b);

//lib.c
#include "lib.h"
int gVar = 3; //定義變量
int addTwo(int a, int b)
{
    return a+b;
}
//A.h
#include "lib.h"

//A.c
#include "A.h"

int main()
{
    int sum = addTwo(1,2);
    printf("sum=%d\n", sum);
    printf("%d\n", gVar);
    return 0;
}

程序正常輸出。

因為在lib.h中只是聲明了gVar且為extern,所以在A.o和lib.o的鏈接過程中,A.o使用的gVar會到其他模塊lib.o中尋找gVar的定義,找到為3。

實際代碼會更加復雜,此處幾個實例簡單地剝離來討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM