博客專欄

        EEPW首頁 > 博客 > C++中關于函數的extern鏈接性以及extern關鍵字

        C++中關于函數的extern鏈接性以及extern關鍵字

        發布人:電子禪石 時間:2020-02-20 來源:工程師 發布文章

        C++中extern關鍵字主要有三種作用,即聲明變量的鏈接性、函數的鏈接性、以及語言的鏈接性。所謂的鏈接性(linkage)是指名稱如何在不同的編譯單元間共享。與其相應的是作用域(scope),它描述的是名稱在一個編譯單元的多大范圍內可見。

        變量的鏈接性:由于C++中變量具有單定義規則(one definiton rule)(只能被定義一次),那么在同一個工程的其他文件中,如果要想使用一個已經定義的變量,只能使用聲明(declaration)。一個全局變量的默認鏈接性是只在本文件可見,在另外一個文件中可以使用extern來聲明這個變量,表示該變量已經在它處定義,從而使得該變量在“變量聲明”所在的文件同樣可見,達到共享的目的。

        函數的鏈接性:默認情況下函數的鏈接性是外部的,即可以在文件間共享。可以使用extern來指出這一點,即該函數是在另外一個文件中定義的,不過這是可選的。但是如果用static來修飾函數的話,那么其鏈接性就是內部的。
        如果用static修飾函數的鏈接性,必須同時給出函數原型以及定義。

        static int private(double x);
        ...
        static int private(double x)
        {
            ...
        }

          

        語言的鏈接性:在C語言中函數是不能重載的,因此在編譯后,一個函數名對應于一個翻譯后的符號名,例如 test(int),對應于_test。但是C++是可以重載的,因此函數經編譯器翻譯后的名稱會有所不同。例如會將test(int),對應于_test_i。但是可以使用extern “C”來告訴編譯器不要按照C++默認的方式翻譯,而使用類似于C的方式翻譯。

        下面通過示例來具體說下函數的鏈接性。
        首先,函數的默認鏈接性是外部的。

        //func.cpp
        #include <iostream>

        void func()
        {
            std::cout<<"Location:func.cpp->func()"<<std::endl;
        }

        //main.cpp
        #include <iostream>

        void func();//or extern void func();

        int main()
        {
            func();
            return 0;
        }

          

        編譯:g++ -g func.cpp main.cpp -o run
        在func.cpp中定義了函數func(),要在main.cpp中使用這個函數的話,必須在main.cpp中先聲明這個函數。注意這里func.cpp和main.cpp是兩個獨立的編譯單元,通過在main.cpp中聲明函數,來實現函數在文件間的共享。在編譯時必須同時包含這兩個cpp文件。

        其次,可以使用static修飾函數,來限制函數的鏈接性。
        如果在上面的函數中將func.cpp中的func()函數用static來修飾,同時給出函數的實現,即

        static void func()
        {
            std::cout<<"Location:func.cpp->func()"<<endl;
        }

            1
            2
            3
            4

        那么即使在main.cpp中聲明函數也是無法進行編譯的,可能編譯錯誤提示如下:

        /tmp/ccoMrixR.o: In function `main':
        /home/project/extern/main.cpp:7: undefined reference to `func()'
        collect2: ld returned 1 exit status


        最后,我的一位同事給我拋出了這樣的一個“疑問”:如果將func()函數放在func.h中,然后在mian.cpp中包含著func.h,那么無論是否用static修飾函數都是可行的,這不是有悖于上面的闡述嗎?或者說如果這樣可行的話,那么函數鏈接性的意義在哪兒了?

        //func.h
        #include <iostream>

        void func()
        {
            std::cout<<"Location:func.cpp->func()"<<std::endl;
        }

        //main.cpp
        #include <iostream>
        #include "func.h"
        void func();

        int main()
        {
            func();
            return 0;
        }

         
         
        實際上這并不矛盾,因為當包含這個函數進行編譯時,func.h和main.cpp并不是兩個不同的編譯單元,當然所謂函數鏈接性也就無從談起。當#include “func.h”,編譯main.cpp時,會將頭文件進行展開,他們是同一個編譯單元。
        ————————————————

        原文鏈接:https://blog.csdn.net/cjf_wei/article/details/66500244

        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: C++

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 翁源县| 平凉市| 凤城市| 永城市| 石河子市| 新昌县| 伊宁市| 安远县| 阿克| 法库县| 星子县| 鹰潭市| 怀宁县| 新和县| 奇台县| 独山县| 新竹市| 德格县| 汶上县| 黄梅县| 揭阳市| 开封县| 北安市| 尼玛县| 崇左市| 河源市| 石城县| 同仁县| 定结县| 自贡市| 怀仁县| 军事| 浦江县| 兴义市| 偏关县| 广州市| 城步| 商都县| 金乡县| 宝兴县| 泸州市|