亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

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

2020-01-26 15:09:31
字體:
來源:轉載
供稿:網友

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

符號

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

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

復制代碼 代碼如下:

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

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


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

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

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

0000000000000000 T _Z5helloPKc 
                 U __gxx_personality_v0 
0000000000000000 D g_prefix 
                 U printf 

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

1、 符號以_Z開始
2、 如果有嵌套,后面緊跟N,然后是名稱空間、類、函數的名字,名字前的數字是長度,以E結尾
3、 如果沒嵌套,則直接是名字長度后面跟著名字
4、 最后是參數列表,類型和符號對應關系如下

復制代碼 代碼如下:

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

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

下面列舉幾個函數和符號的對應例子

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

復制代碼 代碼如下:

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

    int var = 42; 

 
extern int _ZN6myname3varE; 
 
int main() 

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

這里我們在名稱空間namespace定義了全局變量var,根據前面的內容,它會被修飾為符號_ZN6myname3varE,然后我們手動聲明了外部變量_ZN6myname3varE并將其打印出來。編譯并運行,它的值正好就是var的值

復制代碼 代碼如下:

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

extern "C"

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

復制代碼 代碼如下:

extern "C" 

    int func(int); 
    int var; 


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

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

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

復制代碼 代碼如下:

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

#endif 

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美性高潮床叫视频| 亚洲国产小视频在线观看| 国产91精品网站| 色噜噜狠狠色综合网图区| 亚洲免费一级电影| 国产美女精品视频免费观看| 亚洲片国产一区一级在线观看| 亚洲欧美在线一区二区| 国产精品高潮粉嫩av| 亚洲乱码国产乱码精品精天堂| 日本免费久久高清视频| 国产精品免费视频久久久| 亚洲欧美另类中文字幕| 在线观看欧美视频| 日日骚av一区| 国产综合在线观看视频| 中文字幕成人精品久久不卡| 国产激情久久久久| 亚洲成人免费网站| 久久电影一区二区| 国产精品www色诱视频| 亚洲精品白浆高清久久久久久| 国产精品久久久久久久app| 中文字幕日本欧美| 欧美香蕉大胸在线视频观看| 久久国产精品久久精品| 人体精品一二三区| 日韩av免费看网站| 国产v综合ⅴ日韩v欧美大片| 欧美精品日韩www.p站| 亚洲国产精品成人精品| 蜜月aⅴ免费一区二区三区| 日韩一中文字幕| 国产精品91在线观看| 91久久精品一区| 日韩av在线看| 高清一区二区三区四区五区| 欧美成人免费一级人片100| www.色综合| 亚洲成人a级网| 亚洲欧美在线一区二区| 国产精品jizz在线观看麻豆| 欧美成在线观看| 欧美激情视频一区| 国内免费久久久久久久久久久| 日韩日本欧美亚洲| 国产精品69精品一区二区三区| 秋霞成人午夜鲁丝一区二区三区| 国产精品青青在线观看爽香蕉| 岛国av午夜精品| 欧美综合在线观看| 欧美极品少妇xxxxⅹ裸体艺术| 精品二区三区线观看| 久久久精品欧美| 国产欧美精品日韩| 青青草成人在线| 亚洲欧美制服第一页| 911国产网站尤物在线观看| 亚洲精品国产欧美| 亚洲国产精品悠悠久久琪琪| 538国产精品一区二区免费视频| 色噜噜亚洲精品中文字幕| 欧美一级淫片丝袜脚交| 国产日本欧美一区二区三区在线| 亚洲欧美一区二区三区四区| 国产精品看片资源| 国产综合久久久久| 欧美中文在线观看| 欧美在线视频观看免费网站| 国产91在线视频| 亚洲自拍偷拍第一页| 日本国产高清不卡| 伊人精品在线观看| 国产视频久久久久| 精品国偷自产在线视频99| 亚洲综合中文字幕在线观看| 国产精品成人免费视频| 亚洲a∨日韩av高清在线观看| 欧美最猛性xxxxx(亚洲精品)| 久久亚洲精品中文字幕冲田杏梨| 色老头一区二区三区在线观看| 欧美乱大交做爰xxxⅹ性3| 国产91久久婷婷一区二区| 欧美做受高潮电影o| 日韩高清a**址| 一区二区三区国产在线观看| 欧美亚洲国产视频小说| 精品香蕉一区二区三区| 一本一本久久a久久精品牛牛影视| 国产精品福利无圣光在线一区| 国产精品成人一区二区| 欧美日韩免费观看中文| 黑人极品videos精品欧美裸| 永久免费精品影视网站| 欧美精品久久久久久久免费观看| 欧美成人小视频| 久久久久九九九九| 成人激情视频小说免费下载| 成人午夜在线影院| 欧美激情三级免费| 日韩av免费一区| 国产美女精品视频| 97精品国产91久久久久久| 国产精品成人免费电影| 91精品免费久久久久久久久| 亚洲天堂一区二区三区| 久久精品视频播放| 成人久久精品视频| 精品成人av一区| 911国产网站尤物在线观看| 国产精品久久久久久亚洲调教| 欧美成人免费小视频| 国模精品视频一区二区| 欧洲亚洲免费在线| 欧美性生活大片免费观看网址| 欧美性在线观看| 中文字幕在线观看日韩| 亚洲男人天堂2019| 午夜精品www| 久久久精品一区二区三区| 日韩av高清不卡| 国产精品视频公开费视频| 国产精品日韩在线| 一区二区在线视频| 成人性教育视频在线观看| 欧美另类老肥妇| 亚洲成人久久久| 亚洲aⅴ男人的天堂在线观看| 欧美日韩一区二区在线| 亚洲午夜国产成人av电影男同| 3344国产精品免费看| 亚洲欧美日韩久久久久久| 国产欧美日韩中文| 亚洲天堂影视av| 国产国产精品人在线视| 搡老女人一区二区三区视频tv| www.日本久久久久com.| 欧美色播在线播放| 91精品久久久久久久久久另类| 91中文字幕在线| 精品无人国产偷自产在线| 国产精品偷伦一区二区| 美乳少妇欧美精品| 日韩在线观看免费高清| 欧美在线国产精品| 欧美精品18videos性欧| 亚洲电影av在线| 久久成人免费视频| 最近2019中文字幕在线高清| 日韩精品久久久久久福利| 超在线视频97| 国产精品日韩电影| 欧美在线视频免费| 日韩色av导航| 久久精品视频播放| 欧美日韩国产第一页| 亚洲欧美激情一区| 欧美日韩在线视频一区| 欧美另类在线播放| 欧美午夜精品伦理| 国产福利精品视频| www.国产精品一二区| 中文字幕在线国产精品| 亚洲精品一二区|