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

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

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

1 什么是鏈接器

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

截圖

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

2 聲明與定義

extern int a;

上面的這段代碼并不是對a的定義,而是說明a是一個外部整型變量。

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

int a;
extern int a;

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

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

int a = 7;

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

int a = 9;

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

3 命名沖突

3.1 命名沖突

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

int a;

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

3.2 static修飾符

static int a;

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

4 形參、實參、返回值

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

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

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

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

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

實際上,上面這種寫法與下面這種寫法是等價的:

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;
}

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

0 1 2 3 4

實際上,這個程序并不一定得到上面的結(jié)果。例如,在某個編譯器上,它的輸出是(當(dāng)然,在VS2019環(huán)境下程序會崩潰,因為非法修改了內(nèi)存空間)

0 0 0 0 0 1 2 3 4

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

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

5 檢查外部類型

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

例如,在一個文件中包含定義:

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

而在另一個文件中包含聲明:

extern char *filename;

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

image-20220304221554347

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

image-20220304221842175

修改方法如下圖所示:

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

也可以這樣進行修改:

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

6 頭文件

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

    linux之sort命令的用法

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

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

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

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

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

    C語言實現(xiàn)統(tǒng)計一行字符串的單詞個數(shù)

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

    Java C++ 算法題解leetcode1582二進制矩陣特殊位置

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

    C語言輸入一個字符串的方法有哪些

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

最新評論