欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言?超詳細(xì)講解鏈接器

 更新時(shí)間:2022年03月25日 15:03:25   作者:鹿九丸  
在C語(yǔ)言中,一個(gè)重要的思想就是分別編譯,即若干個(gè)源程序能夠在不一樣的時(shí)候單獨(dú)進(jìn)行編譯,而后在恰當(dāng)?shù)臅r(shí)候整合到一塊兒??墒擎溄悠魍ǔJ桥cC編譯器分離的,鏈接器如何作到把若干個(gè)C源程序合并成一個(gè)總體呢,我們一起來(lái)看看

1 什么是鏈接器

典型的鏈接器把由編譯器或匯編器生成的若干個(gè)目標(biāo)模塊,整合成一個(gè)被稱(chēng)為載入模塊或可執(zhí)行文件的實(shí)體–該實(shí)體能夠被操作系統(tǒng)直接執(zhí)行。

截圖

鏈接器通常把目標(biāo)模塊看成是由一組外部對(duì)象組成的。每個(gè)外部對(duì)象代表著機(jī)器內(nèi)存中的某個(gè)部分,并通過(guò)一個(gè)外部名稱(chēng)來(lái)識(shí)別。因此,==程序中的每個(gè)函數(shù)和每個(gè)外部變量,如果沒(méi)有被聲明為static,就都是一個(gè)外部對(duì)象。==某些C編譯器會(huì)對(duì)靜態(tài)函數(shù)和靜態(tài)變量的名稱(chēng)做一定改變,將它們也作為外部對(duì)象。由于經(jīng)過(guò)了“名稱(chēng)修飾”,因此它們不會(huì)與其它源程序文件中的同名函數(shù)或同名變量發(fā)生命名沖突。

2 聲明與定義

extern int a;

上面的這段代碼并不是對(duì)a的定義,而是說(shuō)明a是一個(gè)外部整型變量。

注意:引入之后,假如引入的位置在函數(shù)之外,就相當(dāng)于在那個(gè)位置定義了全局變量,同樣遵循局部變量?jī)?yōu)先原則,如果引入位置在某個(gè)函數(shù)之內(nèi),就相當(dāng)于是一個(gè)局部變量,作用域與那個(gè)地方定義的局部變量相類(lèi)似,此處討論聲明周期沒(méi)有任何意義。

int a;
extern int a;

上面的這兩條語(yǔ)句既可以是在同一個(gè)源文件中,也可以位于程序的不同源文件之中。

==注意:每個(gè)外部變量只能定義一次。==如果外部變量的多個(gè)定義各指定一個(gè)初始值,例如:

int a = 7;

出現(xiàn)在一個(gè)源文件中,而

int a = 9;

出現(xiàn)在另一個(gè)源文件中,大多數(shù)系統(tǒng)都會(huì)拒絕接收該程序。但是,如果一個(gè)外部變量在多個(gè)源文件中定義卻沒(méi)有指定初始值,那么**某些系統(tǒng)會(huì)接受這個(gè)程序,而另外一些系統(tǒng)則不會(huì)接受。**所以,每個(gè)外部變量必須只定義一次。

3 命名沖突

3.1 命名沖突

如果在兩個(gè)不同的源文件中都包括了定義

int a;

那么它要么表示程序錯(cuò)誤(如果鏈接器進(jìn)制外部變量重復(fù)命名的話),要么在兩個(gè)源文件中共享a的同一個(gè)實(shí)例(無(wú)論兩個(gè)源文件中的外部變量是否應(yīng)該被共享)。即使其中a的一個(gè)定義是出現(xiàn)在系統(tǒng)提供的庫(kù)文件中,也仍然進(jìn)行同樣的處理。

3.2 static修飾符

static int a;

static修飾a之后,a的作用域?qū)⒈幌拗圃谝粋€(gè)源文件中,對(duì)于其它源文件,a是不可見(jiàn)的,且無(wú)法再被extern所引用,當(dāng)然,static也適用于函數(shù)。使用static之后,我們就可以在其它的源文件中定義和這個(gè)已經(jīng)被static修飾后的同名的變量或者函數(shù)。

4 形參、實(shí)參、返回值

如果我們使用的函數(shù)并未進(jìn)行聲明,但是已經(jīng)在后面進(jìn)行了定義,此時(shí)會(huì)默認(rèn)函數(shù)返回類(lèi)型為int型,這會(huì)造成極其嚴(yán)重的后果。

使用的函數(shù)如果在使用之前并未定義或者可能在其他的文件中,那么就要進(jìn)行聲明,函數(shù)聲明的目的就是告知編譯器函數(shù)的返回值的類(lèi)型。

注意:如果一個(gè)函數(shù)沒(méi)有float、short、或者char類(lèi)型的參數(shù),在函數(shù)聲明中完全可以省略掉參數(shù)類(lèi)型的說(shuō)明(注意,函數(shù)定義中不能省略參數(shù)類(lèi)型的說(shuō)明)。這種做法依賴(lài)于調(diào)用者能夠提供數(shù)目正確且類(lèi)型恰當(dāng)?shù)膶?shí)參。這里,“恰當(dāng)”并不意味著“等同”:float類(lèi)型的參數(shù)會(huì)自動(dòng)轉(zhuǎn)換為double類(lèi)型,short或者char類(lèi)型的參數(shù)會(huì)自動(dòng)轉(zhuǎn)換為int類(lèi)型。

在ANSI C標(biāo)準(zhǔn)發(fā)布之前,常常會(huì)有下面的這種聲明和定義函數(shù)的方式:

int isvowel();//聲明函數(shù)的方式
int isvowel(c)
		char c;
{
	return c =='a' ;
}

實(shí)際上,上面這種寫(xiě)法與下面這種寫(xiě)法是等價(jià)的:

int isvowel(int i)
{
	char c;
	return c=='a';
}

上述兩種方式在VS2019中都是支持的。

看下面的例子:

#include<stdio.h>
int main()
{
	int i;
	char c;
	for (i = 0; i < 5; i++)
	{
		scanf("%d", &c);
		printf("%d ", i);
	}
	printf("\n");
	return 0;
}

表面上,這個(gè)程序從標(biāo)準(zhǔn)輸入設(shè)備讀入5個(gè)數(shù),在標(biāo)準(zhǔn)輸出設(shè)備設(shè)備上寫(xiě)5個(gè)數(shù):

0 1 2 3 4

實(shí)際上,這個(gè)程序并不一定得到上面的結(jié)果。例如,在某個(gè)編譯器上,它的輸出是(當(dāng)然,在VS2019環(huán)境下程序會(huì)崩潰,因?yàn)榉欠ㄐ薷牧藘?nèi)存空間)

0 0 0 0 0 1 2 3 4

為什么呢?問(wèn)題的關(guān)鍵在于,這里的c被聲明為char類(lèi)型,而不是int類(lèi)型。如果程序要求scanf讀入一個(gè)整數(shù),應(yīng)該傳遞給他一個(gè)指向整數(shù)的指針。而程序中scanf函數(shù)得到的卻是一個(gè)指向字符的指針,scanf函數(shù)并不能分辨這種情況,它只是將這個(gè)指向字符的指針作為指向整數(shù)的指針而接受,并且在指針指向的位置存儲(chǔ)一個(gè)整數(shù)。因?yàn)檎麛?shù)所占的存儲(chǔ)空間要大于字符所占的存儲(chǔ)空間,所以字符c附近的內(nèi)存被覆蓋。

字符c附近的內(nèi)存中存儲(chǔ)的內(nèi)容是由編譯器決定的,在本例中它所存放的是整數(shù)i的低端部分。因此,每次讀入一個(gè)數(shù)值到c時(shí),都會(huì)將i的低端部分覆蓋為0,而i的高端部分本來(lái)就是0,相當(dāng)于i每次被重新設(shè)置為0,循環(huán)將一直進(jìn)行。當(dāng)?shù)竭_(dá)文件的結(jié)束位置后,scanf函數(shù)不再試圖讀入新的值到c。這時(shí),i才可以正常的運(yùn)行,最后終止循環(huán)。

5 檢查外部類(lèi)型

注意:保證一個(gè)特定類(lèi)型的所有外部定義在每個(gè)目標(biāo)模塊中都有相同的類(lèi)型,“相同的類(lèi)型”也應(yīng)該是嚴(yán)格意義上的相同。

例如,在一個(gè)文件中包含定義:

char filename[] = "/etc/passwd";

而在另一個(gè)文件中包含聲明:

extern char *filename;

在定義時(shí),filename是一個(gè)字符數(shù)組的名稱(chēng)。盡管在一個(gè)語(yǔ)句中引用filename的值將得到指向該數(shù)組起始元素的指針,但是filename的類(lèi)型是”字符數(shù)組“,而不是字符指針。在第二個(gè)聲明中,filename被確定為一個(gè)指針。這兩種方式使用存儲(chǔ)空間的方式是不同的,它們無(wú)法以一種合乎情理的方式共存。第一個(gè)例子字符數(shù)組filename的內(nèi)存布局如下圖所示:

image-20220304221554347

第二種方式字符指針filename的內(nèi)存布局如下圖所示:

image-20220304221842175

修改方法如下圖所示:

char filename[] = "/etc/passwd";
extern char filename[];

也可以這樣進(jìn)行修改:

char*filename = "/etc/passwd";
extern char *filename;

6 頭文件

注意:每個(gè)外部對(duì)象只在一個(gè)地方聲明,這個(gè)聲明的地方一般就在頭文件種,需要用到該外部對(duì)象的所有模塊也應(yīng)該 包括在這個(gè)頭文件。特別指出的是,定義該外部對(duì)象的模塊也應(yīng)該包括這個(gè)頭文件。

到此這篇關(guān)于C語(yǔ)言?超詳細(xì)講解鏈接器的文章就介紹到這了,更多相關(guān)C語(yǔ)言 鏈接器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解C語(yǔ)言中的Static關(guān)鍵字

    詳解C語(yǔ)言中的Static關(guān)鍵字

    這篇文章主要為大家介紹了C語(yǔ)言中Static關(guān)鍵字,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • 關(guān)于C++中二分法詳解

    關(guān)于C++中二分法詳解

    大家好,本篇文章主要講的是關(guān)于C++中二分法詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • 結(jié)構(gòu)體類(lèi)型數(shù)據(jù)作為函數(shù)參數(shù)(三種方法)

    結(jié)構(gòu)體類(lèi)型數(shù)據(jù)作為函數(shù)參數(shù)(三種方法)

    將一個(gè)結(jié)構(gòu)體中變量中的數(shù)據(jù)傳遞給另一個(gè)函數(shù),有以下三種方法。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2013-10-10
  • C語(yǔ)言細(xì)致講解線程同步的集中方式

    C語(yǔ)言細(xì)致講解線程同步的集中方式

    多線程中的線程同步可以使用,CreateThread,CreateMutex 互斥鎖實(shí)現(xiàn)線程同步,通過(guò)臨界區(qū)實(shí)現(xiàn)線程同步,Semaphore 基于信號(hào)實(shí)現(xiàn)線程同步,CreateEvent 事件對(duì)象的同步,以及線程函數(shù)傳遞單一參數(shù)與多個(gè)參數(shù)的實(shí)現(xiàn)方式
    2022-05-05
  • linux之sort命令的用法

    linux之sort命令的用法

    sort將文件的每一行作為一個(gè)單位,相互比較,比較原則是從首字符向后,依次按ASCII碼值進(jìn)行比較,最后將他們按升序輸出
    2013-10-10
  • C++數(shù)據(jù)結(jié)構(gòu)之二叉搜索樹(shù)的實(shí)現(xiàn)詳解

    C++數(shù)據(jù)結(jié)構(gòu)之二叉搜索樹(shù)的實(shí)現(xiàn)詳解

    二叉搜索樹(shù)作為一個(gè)經(jīng)典的數(shù)據(jù)結(jié)構(gòu),具有鏈表的快速插入與刪除的特點(diǎn),同時(shí)查詢(xún)效率也很優(yōu)秀,所以應(yīng)用十分廣泛。本文將詳細(xì)講講二叉搜索樹(shù)的C++實(shí)現(xiàn),需要的可以參考一下
    2022-08-08
  • C++的matlab接口轉(zhuǎn)換方法詳解

    C++的matlab接口轉(zhuǎn)換方法詳解

    這篇文章主要為大家詳細(xì)介紹了C++的matlab接口轉(zhuǎn)換方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • C語(yǔ)言實(shí)現(xiàn)統(tǒng)計(jì)一行字符串的單詞個(gè)數(shù)

    C語(yǔ)言實(shí)現(xiàn)統(tǒng)計(jì)一行字符串的單詞個(gè)數(shù)

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)統(tǒng)計(jì)一行字符串的單詞個(gè)數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Java C++ 算法題解leetcode1582二進(jìn)制矩陣特殊位置

    Java C++ 算法題解leetcode1582二進(jìn)制矩陣特殊位置

    這篇文章主要為大家介紹了Java C++ 算法題解leetcode1582二進(jìn)制矩陣特殊位置示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • C語(yǔ)言輸入一個(gè)字符串的方法有哪些

    C語(yǔ)言輸入一個(gè)字符串的方法有哪些

    字符串輸入是C語(yǔ)言編程中非常重要的部分,其中scanf函數(shù)是一種廣泛使用的輸入字符串的方法,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言輸入一個(gè)字符串的方法有哪些的相關(guān)資料,需要的朋友可以參考下
    2023-06-06

最新評(píng)論