欧美大屁股bbbbxxxx,狼人大香伊蕉国产www亚洲,男ji大巴进入女人的视频小说,男人把ji大巴放进女人免费视频,免费情侣作爱视频

歡迎來到入門教程網(wǎng)!

C語言

當(dāng)前位置:主頁 > 軟件編程 > C語言 >

實(shí)例詳解C/C++中extern關(guān)鍵字

來源:本站原創(chuàng)|時(shí)間:2020-01-10|欄目:C語言|點(diǎn)擊: 次

1 基本解釋:extern可以置于變量或者函數(shù)前,以標(biāo)示變量或者函數(shù)的定義在別的文件中,提示編譯器遇到此變量和函數(shù)時(shí)在其他模塊中尋找其定義。此外extern也可用來進(jìn)行鏈接指定。

也就是說extern有兩個(gè)作用,第一個(gè),當(dāng)它與"C"一起連用時(shí),如: extern "C" void fun(int a, int b);則告訴編譯器在編譯fun這個(gè)函數(shù)名時(shí)按著C的規(guī)則去翻譯相應(yīng)的函數(shù)名而不是C++的,C++的規(guī)則在翻譯這個(gè)函數(shù)名時(shí)會(huì)把fun這個(gè)名字變得面目全非,可能是fun@aBc_int_int#%$也可能是別的,這要看編譯器的"脾氣"了(不同的編譯器采用的方法不一樣),為什么這么做呢,因?yàn)镃++支持函數(shù)的重載啊,在這里不去過多的論述這個(gè)問題,如果你有興趣可以去網(wǎng)上搜索,相信你可以得到滿意的解釋!

第二,當(dāng)extern不與"C"在一起修飾變量或函數(shù)時(shí),如在頭文件中: extern int g_Int; 它的作用就是聲明函數(shù)或全局變量的作用范圍的關(guān)鍵字,其聲明的函數(shù)和變量可以在本模塊活其他模塊中使用,記住它是一個(gè)聲明不是定義!也就是說B模塊(編譯單元)要是引用模塊(編譯單元)A中定義的全局變量或函數(shù)時(shí),它只要包含A模塊的頭文件即可,在編譯階段,模塊B雖然找不到該函數(shù)或變量,但它不會(huì)報(bào)錯(cuò),它會(huì)在連接時(shí)從模塊A生成的目標(biāo)代碼中找到此函數(shù)。

2 問題:extern 變量

  在一個(gè)源文件里定義了一個(gè)數(shù)組:char a[6];

  在另外一個(gè)文件里用下列語句進(jìn)行了聲明:extern char *a;

  請(qǐng)問,這樣可以嗎?

  答案與分析:

  1)、不可以,程序運(yùn)行時(shí)會(huì)告訴你非法訪問。原因在于,指向類型T的指針并不等價(jià)于類型T的數(shù)組。extern char *a聲明的是一個(gè)指針變量而不是字符數(shù)組,因此與實(shí)際的定義不同,從而造成運(yùn)行時(shí)非法訪問。應(yīng)該將聲明改為extern char a[ ]。

  2)、例子分析如下,如果a[] = "abcd",則外部變量a=0x61626364 (abcd的ASCII碼值),*a顯然沒有意義

  顯然a指向的空間(0x61626364)沒有意義,易出現(xiàn)非法內(nèi)存訪問。

  3)、這提示我們,在使用extern時(shí)候要嚴(yán)格對(duì)應(yīng)聲明時(shí)的格式,在實(shí)際編程中,這樣的錯(cuò)誤屢見不鮮。

  4)、extern用在變量聲明中常常有這樣一個(gè)作用,你在*.c文件中聲明了一個(gè)全局的變量,這個(gè)全局的變量如果要被引用,就放在*.h中并用extern來聲明。

3 問題:當(dāng)方面修改extern 函數(shù)原型

  當(dāng)函數(shù)提供方單方面修改函數(shù)原型時(shí),如果使用方不知情繼續(xù)沿用原來的extern申明,這樣編譯時(shí)編譯器不會(huì)報(bào)錯(cuò)。但是在運(yùn)行過程中,因?yàn)樯倭嘶蛘叨嗔溯斎雲(yún)?shù),往往會(huì)照成系統(tǒng)錯(cuò)誤,這種情況應(yīng)該如何解決?

  答案與分析:

  目前業(yè)界針對(duì)這種情況的處理沒有一個(gè)很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供對(duì)外部接口的聲明,然后調(diào)用方include該頭文件,從而省去extern這一步。以避免這種錯(cuò)誤。

  寶劍有雙鋒,對(duì)extern的應(yīng)用,不同的場(chǎng)合應(yīng)該選擇不同的做法。

4 問題:extern “C”

  在C++環(huán)境下使用C函數(shù)的時(shí)候,常常會(huì)出現(xiàn)編譯器無法找到obj模塊中的C函數(shù)定義,從而導(dǎo)致鏈接失敗的情況,應(yīng)該如何

解決這種情況呢?

  答案與分析:

  C++語言在編譯的時(shí)候?yàn)榱私鉀Q函數(shù)的多態(tài)問題,會(huì)將函數(shù)名和參數(shù)聯(lián)合起來生成一個(gè)中間的函數(shù)名稱,而C語言則不會(huì),因此會(huì)造成鏈接時(shí)找不到對(duì)應(yīng)函數(shù)的情況,此時(shí)C函數(shù)就需要用extern “C”進(jìn)行鏈接指定,這告訴編譯器,請(qǐng)保持我的名稱,不要給我生成用于鏈接的中間函數(shù)名。

  下面是一個(gè)標(biāo)準(zhǔn)的寫法:

//在.h文件的頭上
#ifdef __cplusplus
#if __cplusplus
extern "C"{
 #endif
 #endif /* __cplusplus */ 
 …
 …
 //.h文件結(jié)束的地方
 #ifdef __cplusplus
 #if __cplusplus
}
#endif
#endif /* __cplusplus */ 

5 問題:extern 函數(shù)聲明

  常常見extern放在函數(shù)的前面成為函數(shù)聲明的一部分,那么,C語言的關(guān)鍵字extern在函數(shù)的聲明中起什么作用?

  答案與分析:

  如果函數(shù)的聲明中帶有關(guān)鍵字extern,僅僅是暗示這個(gè)函數(shù)可能在別的源文件里定義,沒有其它作用。即下述兩個(gè)函數(shù)聲明沒有明顯的區(qū)別:

extern int f(); 和int f();

  當(dāng)然,這樣的用處還是有的,就是在程序中取代include “*.h”來聲明函數(shù),在一些復(fù)雜的項(xiàng)目中,我比較習(xí)慣在所有的函數(shù)聲明前添加extern修飾。關(guān)于這樣做的原因和利弊可見下面的這個(gè)例子:“用extern修飾的全局變量”

(1) 在test1.h中有下列聲明:

#ifndef TEST1H
#define TEST1H
extern char g_str[]; // 聲明全局變量g_str
void fun1();
#endif

(2) 在test1.cpp中

#include "test1.h"
char g_str[] = "123456"; // 定義全局變量g_str
void fun1() { cout << g_str << endl; }

(3) 以上是test1模塊, 它的編譯和連接都可以通過,如果我們還有test2模塊也想使用g_str,只需要在原文件中引用就可以了

#include "test1.h"
void fun2() { cout << g_str << endl; }

以上test1和test2可以同時(shí)編譯連接通過,如果你感興趣的話可以用ultraEdit打開test1.obj,你可以在里面找到"123456"這個(gè)字符串,但是你卻不能在test2.obj里面找到,這是因?yàn)間_str是整個(gè)工程的全局變量,在內(nèi)存中只存在一份,test2.obj這個(gè)編譯單元不需要再有一份了,不然會(huì)在連接時(shí)報(bào)告重復(fù)定義這個(gè)錯(cuò)誤!

(4) 有些人喜歡把全局變量的聲明和定義放在一起,這樣可以防止忘記了定義,如把上面test1.h改為
extern char g_str[] = "123456"; // 這個(gè)時(shí)候相當(dāng)于沒有extern

然后把test1.cpp中的g_str的定義去掉,這個(gè)時(shí)候再編譯連接test1和test2兩個(gè)模塊時(shí),會(huì)報(bào)連接錯(cuò)誤,這是因?yàn)槟惆讶肿兞縢_str的定義放在了頭文件之后,test1.cpp這個(gè)模塊包含了test1.h所以定義了一次g_str,而test2.cpp也包含了test1.h所以再一次定義了g_str,這個(gè)時(shí)候連接器在連接test1和test2時(shí)發(fā)現(xiàn)兩個(gè)g_str。如果你非要把g_str的定義放在test1.h中的話,那么就把

test2的代碼中#include "test1.h"去掉 換成:

extern char g_str[];
void fun2() { cout << g_str << endl; }

這個(gè)時(shí)候編譯器就知道g_str是引自于外部的一個(gè)編譯模塊了,不會(huì)在本模塊中再重復(fù)定義一個(gè)出來,但是我想說這樣做非常糟糕,因?yàn)槟阌捎跓o法在test2.cpp中使用#include "test1.h",那么test1.h中聲明的其他函數(shù)你也無法使用了,除非也用都用extern修飾,這樣的話你光聲明的函數(shù)就要一大串,而且頭文件的作用就是要給外部提供接口使用的,所以 請(qǐng)記住, 只在頭文件中做聲明,真理總是這么簡(jiǎn)單。

6. extern 和 static

(1) extern 表明該變量在別的地方已經(jīng)定義過了,在這里要使用那個(gè)變量.

(2) static 表示靜態(tài)的變量,分配內(nèi)存的時(shí)候, 存儲(chǔ)在靜態(tài)區(qū),不存儲(chǔ)在棧上面.

static 作用范圍是內(nèi)部連接的關(guān)系, 和extern有點(diǎn)相反.它和對(duì)象本身是分開存儲(chǔ)的,extern也是分開存儲(chǔ)的,但是extern可以被其他的對(duì)象用extern 引用,而static 不可以,只允許對(duì)象本身用它. 具體差別首先,static與extern是一對(duì)“水火不容”的家伙,也就是說extern和static不能同時(shí)修飾一個(gè)變量;其次,static修飾的全局變量聲明與定義同時(shí)進(jìn)行,也就是說當(dāng)你在頭文件中使用static聲明了全局變量后,它也同時(shí)被定義了;最后,static修飾全局變量的作用域只能是本身的編譯單元,也就是說它的“全局”只

對(duì)本編譯單元有效,其他編譯單元?jiǎng)t看不到它,如:

(1) test1.h:

#ifndef TEST1H
#define TEST1H
static char g_str[] = "123456"; 
void fun1();
#endif

(2) test1.cpp:

#include "test1.h"
void fun1() { cout << g_str << endl; }

(3) test2.cpp

#include "test1.h"
void fun2() { cout << g_str << endl; }

以上兩個(gè)編譯單元可以連接成功, 當(dāng)你打開test1.obj時(shí),你可以在它里面找到字符串"123456",同時(shí)你也可以在test2.obj中找到它們,它們之所以可以連接成功而沒有報(bào)重復(fù)定義的錯(cuò)誤是因?yàn)殡m然它們有相同的內(nèi)容,但是存儲(chǔ)的物理地址并不一樣,就像是兩個(gè)不同變量賦了相同的值一樣,而這兩個(gè)變量分別作用于它們各自的編譯單元。 也許你比較較真,自己偷偷的跟蹤調(diào)試上面的代碼,結(jié)果你發(fā)現(xiàn)兩個(gè)編譯單元(test1,test2)的g_str的內(nèi)存地址相同,于是你下結(jié)論static修飾的變量也可以作用于其他模塊,但是我要告訴你,那是你的編譯器在欺騙你,大多數(shù)編譯器都對(duì)代碼都有優(yōu)化功能,以達(dá)到生成的目標(biāo)程序更節(jié)省內(nèi)存,執(zhí)行效率更高,當(dāng)編譯器在連接各個(gè)編譯單元的時(shí)候,它會(huì)把相同內(nèi)容的內(nèi)存只拷貝一份,比如上面的"123456", 位于兩個(gè)編譯單元中的變量都是同樣的內(nèi)容,那么在連接的時(shí)候它在內(nèi)存中就只會(huì)存在一份了,如果你把上面的代碼改成下面的樣子,你馬上就可以拆穿編譯器的謊言:

(1) test1.cpp:

#include "test1.h"
void fun1()
{
g_str[0] = ''a'';
cout << g_str << endl;
}

(2) test2.cpp

#include "test1.h"
void fun2() { cout << g_str << endl; }

(3) void main() {

fun1(); // a23456
fun2(); // 123456
}

這個(gè)時(shí)候你在跟蹤代碼時(shí),就會(huì)發(fā)現(xiàn)兩個(gè)編譯單元中的g_str地址并不相同,因?yàn)槟阍谝惶幮薷牧怂跃幾g器被強(qiáng)行的恢復(fù)內(nèi)存的原貌,在內(nèi)存中存在了兩份拷貝給兩個(gè)模塊中的變量使用。正是因?yàn)閟tatic有以上的特性,所以一般定義static全局變量時(shí),都把它放在原文件中而不是頭文件,這樣就不會(huì)給其他模塊造成不必要的信息污染,同樣記住這個(gè)原則吧!

7. extern 和const

C++中const修飾的全局常量據(jù)有跟static相同的特性,即它們只能作用于本編譯模塊中,但是const可以與extern連用來聲明該常量可以作用于其他編譯模塊中, 如extern const char g_str[];

然后在原文件中別忘了定義: const char g_str[] = "123456";

所以當(dāng)const單獨(dú)使用時(shí)它就與static相同,而當(dāng)與extern一起合作的時(shí)候,它的特性就跟extern的一樣了!所以對(duì)const我沒有什么可以過多的描述,我只是想提醒你,const char* g_str = "123456" 與 const char g_str[] ="123465"是不同的, 前面那個(gè)const 修飾的是char *而不是g_str,它的g_str并不是常量,它被看做是一個(gè)定義了的全局變量(可以被其他編譯單元使用), 所以如果你像讓char*g_str遵守const的全局常量的規(guī)則,最好這么定義const char* const g_str="123456".

上一篇:學(xué)習(xí) C++能帶給我們什么

欄    目:C語言

下一篇:舉例講解C語言程序中對(duì)二叉樹數(shù)據(jù)結(jié)構(gòu)的各種遍歷方式

本文標(biāo)題:實(shí)例詳解C/C++中extern關(guān)鍵字

本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2396.html

網(wǎng)頁制作CMS教程網(wǎng)絡(luò)編程軟件編程腳本語言數(shù)據(jù)庫服務(wù)器

如果侵犯了您的權(quán)利,請(qǐng)與我們聯(lián)系,我們將在24小時(shí)內(nèi)進(jìn)行處理、任何非本站因素導(dǎo)致的法律后果,本站均不負(fù)任何責(zé)任。

聯(lián)系QQ:835971066 | 郵箱:835971066#qq.com(#換成@)

Copyright © 2002-2020 腳本教程網(wǎng) 版權(quán)所有