亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++中的extern “C”用法詳解

 更新時(shí)間:2015年03月17日 09:45:03   投稿:junjie  
這篇文章主要介紹了C++中的extern “C”用法詳解,簡單來說,extern “C”是C++聲明或定義C語言符號(hào)的方法,是為了與C兼容,需要的朋友可以參考下

簡單來說,extern “C”是C++聲明或定義C語言符號(hào)的方法,是為了與C兼容。說來容易,要理解起來還是得費(fèi)些周折,首先我們要從C++和C的區(qū)別說起。

符號(hào)

大家都知道,從代碼到可執(zhí)行程序需要經(jīng)過編譯和鏈接兩個(gè)過程,其中編譯階段會(huì)做語法檢測,代碼展開,另外它還會(huì)做一件事,就是將變量轉(zhuǎn)成符號(hào),鏈接的時(shí)候其實(shí)是通過符號(hào)來定位的。編譯器在編譯C和C++代碼時(shí),將變量轉(zhuǎn)成符號(hào)的過程是不同的。本文所使用的編譯器為gcc4.4.7

我們先來看一段簡單的代碼

復(fù)制代碼 代碼如下:

/* hello.c */ 
#include <stdio.h> 
 
const char* g_prefix = "hello "; 
 
void hello(const char* name) 

    printf("%s%s", g_prefix, name); 


注意,這里的文件名為hello.c,我們執(zhí)行編譯gcc -c hello.c得到目標(biāo)文件hello.o,在Linux下用nm查看目標(biāo)文件的符號(hào)表得到如下結(jié)果($符號(hào)代表shell命令提示符)
復(fù)制代碼 代碼如下:

$ nm hello.o 
0000000000000000 D g_prefix 
0000000000000000 T hello 
                 U printf 

這是C代碼編譯后的符號(hào)列表,其中第三列為編譯后的符號(hào)名,我們主要看自己定義的全局變量g_prefix和函數(shù)hello,它們的編譯后的符號(hào)名和代碼里的名字是一樣的。我們將hello.c重命名為hello.cpp,重新編譯gcc -c hello.cpp得到hello.o,在用nm查看,結(jié)果如下
復(fù)制代碼 代碼如下:

0000000000000000 T _Z5helloPKc 
                 U __gxx_personality_v0 
0000000000000000 D g_prefix 
                 U printf 

這是C++代碼編譯后的符號(hào)列表,gcc會(huì)自動(dòng)根據(jù)文件后綴名來識(shí)別C和C++代碼,這時(shí)我們發(fā)現(xiàn)g_prefix的符號(hào)沒變,但函數(shù)hello的符號(hào)變成了_Z5helloPKc,這就說明gcc在編譯C和C++代碼時(shí)處理方式是不一樣的,對于C代碼,變量的符號(hào)名就是變量本身(在早期編譯器會(huì)為C代碼變量前加下劃線_,現(xiàn)在默認(rèn)都不會(huì)了,在編譯時(shí)可以通過編譯選項(xiàng)-fno-leading-underscore和-fleading-underscore來顯式設(shè)置),而對于C++代碼,如果是數(shù)據(jù)變量并且沒有嵌套,符號(hào)名也是本身,如果變量名有嵌套(在名稱空間或類里)或者是函數(shù)名,符號(hào)名就會(huì)按如下規(guī)則來處理

1、 符號(hào)以_Z開始
2、 如果有嵌套,后面緊跟N,然后是名稱空間、類、函數(shù)的名字,名字前的數(shù)字是長度,以E結(jié)尾
3、 如果沒嵌套,則直接是名字長度后面跟著名字
4、 最后是參數(shù)列表,類型和符號(hào)對應(yīng)關(guān)系如下

復(fù)制代碼 代碼如下:

    int    -> i 
    float  -> f 
    double -> d 
    char   -> c 
    void   -> v 
    const  -> K 
    *      -> P 

這樣就很好理解為什么C++代碼里的void hello(const char*)編譯之后符號(hào)為_Z5helloPKc(PKc翻譯成類型要從右到左翻譯為char const *,這是編譯器內(nèi)部的表示方式,我們習(xí)慣的表示方式是const char*,兩者是一樣的),c++filt工具可以從符號(hào)反推名字,使用方法為c++filt _Z5helloPKc

下面列舉幾個(gè)函數(shù)和符號(hào)的對應(yīng)例子

這樣也很容易理解為什么C++支持函數(shù)重載而C不支持了,因?yàn)镃++將函數(shù)修飾為符號(hào)時(shí)把函數(shù)的參數(shù)類型加進(jìn)去了,而C卻沒有,所以在C++下,即便函數(shù)名相同,只要參數(shù)不同,它們的符號(hào)名是不會(huì)沖突的。我們可以通過下面一個(gè)例子來驗(yàn)證變量名和符號(hào)的這種關(guān)系。

復(fù)制代碼 代碼如下:

/ * filename : test.cpp */ 
#include <stdio.h> 
 
namespace myname 

    int var = 42; 

 
extern int _ZN6myname3varE; 
 
int main() 

    printf("%d\n", _ZN6myname3varE); 
    return 0; 
}  

這里我們在名稱空間namespace定義了全局變量var,根據(jù)前面的內(nèi)容,它會(huì)被修飾為符號(hào)_ZN6myname3varE,然后我們手動(dòng)聲明了外部變量_ZN6myname3varE并將其打印出來。編譯并運(yùn)行,它的值正好就是var的值

復(fù)制代碼 代碼如下:

$ gcc test.cpp -o test -lstdc++ 
$ ./test 
42 

extern "C"

有了符號(hào)的概念我們再來看extern “C”的用法就很容易了

復(fù)制代碼 代碼如下:

extern "C" 

    int func(int); 
    int var; 


它的意思就是告訴編譯器將extern “C”后面的括號(hào)里的代碼當(dāng)做C代碼來處理,當(dāng)然我們也可以以單條語句來聲明
復(fù)制代碼 代碼如下:

extern "C" int func(int); 
extern "C" int var; 

這樣就聲明了C類型的func和var。很多時(shí)候我們寫一個(gè)頭文件聲明了一些C語言的函數(shù),而這些函數(shù)可能被C和C++代碼調(diào)用,當(dāng)我們提供給C++代碼調(diào)用時(shí),需要在頭文件里加extern “C”,否則C++編譯的時(shí)候會(huì)找不到符號(hào),而給C代碼調(diào)用時(shí)又不能加extern “C”,因?yàn)镃是不支持這樣的語法的,常見的處理方式是這樣的,我們以C的庫函數(shù)memset為例

復(fù)制代碼 代碼如下:

#ifdef __cplusplus 
extern "C" { 
#endif 
 
void *memset(void*, int, size_t); 
 
#ifdef __cplusplus 

#endif 

其中__cplusplus是C++編譯器定義的一個(gè)宏,如果這份代碼和C++一起編譯,那么memset會(huì)在extern "C"里被聲明,如果是和C代碼一起編譯則直接聲明,由于__cplusplus沒有被定義,所以也不會(huì)有語法錯(cuò)誤。這樣的技巧在系統(tǒng)頭文件里經(jīng)常被用到。

相關(guān)文章

  • C語言pow()函數(shù)實(shí)現(xiàn)求x的y次方的值

    C語言pow()函數(shù)實(shí)現(xiàn)求x的y次方的值

    這篇文章主要介紹了C語言pow()函數(shù)實(shí)現(xiàn)求x的y次方的值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • C++數(shù)組模擬之單鏈表與雙鏈表和棧和隊(duì)列的實(shí)現(xiàn)過程

    C++數(shù)組模擬之單鏈表與雙鏈表和棧和隊(duì)列的實(shí)現(xiàn)過程

    這篇文章主要介紹了C++數(shù)組模擬之單鏈表與雙鏈表和棧和隊(duì)列的實(shí)現(xiàn)過程,了解內(nèi)部原理是為了幫助我們做擴(kuò)展,同時(shí)也是驗(yàn)證了一個(gè)人的學(xué)習(xí)能力,如果你想讓自己的職業(yè)道路更上一層樓,這些底層的東西你是必須要會(huì)的,跟隨下文來具體了解吧
    2023-02-02
  • C++數(shù)據(jù)結(jié)構(gòu)之鏈表的創(chuàng)建

    C++數(shù)據(jù)結(jié)構(gòu)之鏈表的創(chuàng)建

    這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)之鏈表的創(chuàng)建的相關(guān)資料,希望通過本文幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • 你不知道的C++中namespace和using的用法實(shí)例

    你不知道的C++中namespace和using的用法實(shí)例

    在C++語言編寫的程序中,變量和函數(shù)等的作用范圍是有一定限制的,下面這篇文章主要給大家介紹了一些你不知道的C++中namespace和using的用法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • C 語言進(jìn)制之間的轉(zhuǎn)換

    C 語言進(jìn)制之間的轉(zhuǎn)換

    本篇文章主要介紹了C語言進(jìn)制之間的轉(zhuǎn)換,舉例說明并附圖片,幫助大家理解,希望對大家有所幫助
    2016-07-07
  • C語言廣播的使用詳解

    C語言廣播的使用詳解

    顧名思義可以把自己的數(shù)據(jù)發(fā)送給在特定范圍內(nèi)的所有人;我們網(wǎng)絡(luò)編程中的廣播一般是通過特定的廣播地址把自己的數(shù)據(jù)發(fā)送給局域網(wǎng)內(nèi)當(dāng)前在線的客戶端
    2022-05-05
  • C語言宏函數(shù)container of()簡介

    C語言宏函數(shù)container of()簡介

    這篇文章介紹了C語言宏函數(shù)container of(),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • C++圖文并茂分析講解內(nèi)存管理

    C++圖文并茂分析講解內(nèi)存管理

    本章主要介紹C語言與C++的內(nèi)存管理,以C++的內(nèi)存分布作為引入,介紹C++不同于C語言的內(nèi)存管理方式(new delete對比 malloc free),感興趣的朋友來看看吧
    2022-09-09
  • C++?AVL樹的兩單旋和兩雙旋的項(xiàng)目實(shí)踐

    C++?AVL樹的兩單旋和兩雙旋的項(xiàng)目實(shí)踐

    本文主要介紹了C++?AVL樹的兩單旋和兩雙旋的項(xiàng)目實(shí)踐,根據(jù)節(jié)點(diǎn)插入位置的不同,AVL樹的旋轉(zhuǎn)分為四種,下面就來介紹一下,感興趣的可以了解一下
    2024-03-03
  • C語言各種操作符透徹理解上篇

    C語言各種操作符透徹理解上篇

    C 語言提供了豐富的操作符,有:算術(shù)操作符,移位操作符,位操作符,賦值操作符。讓我們通讀本篇來詳細(xì)了解吧
    2022-02-02

最新評論