最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
c語言中函數(shù)與指針的探討 c語言中指針函數(shù)的用法

c語言指針和函數(shù)的問題

C/C++中的函數(shù)參數(shù)傳遞機制

網(wǎng)站建設(shè)、網(wǎng)站設(shè)計,成都做網(wǎng)站公司-創(chuàng)新互聯(lián)已向上千家企業(yè)提供了,網(wǎng)站設(shè)計,網(wǎng)站制作,網(wǎng)絡(luò)營銷等服務(wù)!設(shè)計與技術(shù)結(jié)合,多年網(wǎng)站推廣經(jīng)驗,合理的價格為您打造企業(yè)品質(zhì)網(wǎng)站。

一、 函數(shù)參數(shù)傳遞機制的基本理論

函數(shù)參數(shù)傳遞機制問題在本質(zhì)上是調(diào)用函數(shù)(過程)和被調(diào)用函數(shù)(過程)在調(diào)用發(fā)生時進(jìn)行通信的方法問題?;镜膮?shù)傳遞機制有兩種:值傳遞和引用傳遞。以下討論稱調(diào)用其他函數(shù)的函數(shù)為主調(diào)函數(shù),被調(diào)用的函數(shù)為被調(diào)函數(shù)。

值傳遞(passl-by-value)過程中,被調(diào)函數(shù)的形式參數(shù)作為被調(diào)函數(shù)的局部變量處理,即在堆棧中開辟了內(nèi)存空間以存放由主調(diào)函數(shù)放進(jìn)來的實參的值,從而成為了實參的一個副本。值傳遞的特點是被調(diào)函數(shù)對形式參數(shù)的任何操作都是作為局部變量進(jìn)行,不會影響主調(diào)函數(shù)的實參變量的值。

引用傳遞(pass-by-reference)過程中,被調(diào)函數(shù)的形式參數(shù)雖然也作為局部變量在堆棧中開辟了內(nèi)存空間,但是這時存放的是由主調(diào)函數(shù)放進(jìn)來的實參變量的地址。被調(diào)函數(shù)對形參的任何操作都被處理成間接尋址,即通過堆棧中存放的地址訪問主調(diào)函數(shù)中的實參變量。正因為如此,被調(diào)函數(shù)對形參做的任何操作都影響了主調(diào)函數(shù)中的

實參變量。

二、 C語言中的函數(shù)參數(shù)傳遞機制

在C語言中,值傳遞是唯一可用的參數(shù)傳遞機制。但是據(jù)筆者所知,由于受指針變量作為函數(shù)參數(shù)的影響,有許多朋友還認(rèn)為這種情況是引用傳遞。這是錯誤的。請看下面的代碼:

int swap(int *x, int *y)

{

int temp;

temp = *x; *x = *y; *y = temp;

return temp;

}

void main()

{

int a = 1, b = 2;

int *p1 = a;

int *p2 = b;

swap(p1, p2)

}

函數(shù)swap以兩個指針變量作為參數(shù),當(dāng)main()調(diào)用swap時,是以值傳遞的方式將指針變量p1、p2的值(也就是變量a、b的地址)放在了swap在堆棧中為形式參數(shù)x、y開辟的內(nèi)存單元中。這一點從以下的匯編代碼可以看出(注釋是筆者加的):

22: void main()

23: {

……

……

13: int a = 1, b = 2;

00401088 mov dword ptr [ebp-4],1

0040108F mov dword ptr [ebp-8],2

14: int *p1 = a;

00401096 lea eax,[ebp-4]

00401099 mov dword ptr [ebp-0Ch],eax

15: int *p2 = b;

0040109C lea ecx,[ebp-8]

0040109F mov dword ptr [ebp-10h],ecx

16: swap(p1, p2);

004010A2 mov edx,dword ptr [ebp-10h] ;參數(shù)p2的值進(jìn)棧

004010A5 push edx

004010A6 mov eax,dword ptr [ebp-0Ch] ;參數(shù)p1的值進(jìn)棧

004010A9 push eax

004010AA call @ILT+15(swap) (00401014) ;調(diào)用swap函數(shù)

004010AF add esp,8 ;清理堆棧中的參數(shù)

17: }

閱讀上述代碼要注意,INTEL80x86系列的CPU對堆棧的處理是向下生成,即從高地址單元向低地址單元生成。從上面的匯編代碼可知,main() 在調(diào)用swap之前,先將實參的值按從右至左的順序壓棧,即先p2進(jìn)棧,再p1進(jìn)棧。調(diào)用結(jié)束之后,主調(diào)函數(shù)main()負(fù)責(zé)清理堆棧中的參數(shù)。Swap 將使用這些進(jìn)入堆棧的變量值。下面是swap函

數(shù)的匯編代碼:

14: void swap(int *x, int *y)

15: {

00401030 push ebp

00401031 mov ebp,esp ;ebp指向棧頂

……

……

16: int temp;

17: temp = *x;

4: int temp;

5: temp = *x;

00401048 mov eax,dword ptr [ebp+8] ;操作已存放在堆棧中的p1,將p1置

; 入eax

0040104B mov ecx,dword ptr [eax] ;通過寄存器間址將*p1置入ecx

0040104D mov dword ptr [ebp-4],ecx;經(jīng)由ecx將*p1置入temp變量的內(nèi)

;存單元。以下類似

6: *x = *y;

00401050 mov edx,dword ptr [ebp+8]

00401053 mov eax,dword ptr [ebp+0Ch]

00401056 mov ecx,dword ptr [eax]

00401058 mov dword ptr [edx],ecx

7: *y = temp;

0040105A mov edx,dword ptr [ebp+0Ch]

0040105D mov eax,dword ptr [ebp-4]

00401060 mov dword ptr [edx],eax

8: return temp;

00401062 mov eax,dword ptr [ebp-4]

9: }

由上述匯編代碼基本上說明了C語言中值傳遞的原理,只不過傳遞的是指針的值而已。本文后面還要論述使用引用傳遞的swap函數(shù)。從這些匯編代碼分析,這里我們可以得到以下幾點:

1. 進(jìn)程的堆棧存儲區(qū)是主調(diào)函數(shù)和被調(diào)函數(shù)進(jìn)行通信的主要區(qū)域。

2. C語言中參數(shù)是從右向左進(jìn)棧的。

3. 被調(diào)函數(shù)使用的堆棧區(qū)域結(jié)構(gòu)為:

局部變量(如temp)

返回地址

函數(shù)參數(shù)

低地址

高地址

4. 由主調(diào)函數(shù)在調(diào)用后清理堆棧。

5. 函數(shù)的返回值一般是放在寄存器中的。

這里尚需補充說明幾點:一是參數(shù)進(jìn)棧的方式。對于內(nèi)部類型,由于編譯器知道各類型變量使用的內(nèi)存大小故直接使用push指令;對于自定義的類型(如 structure),采用從源地址向目的(堆棧區(qū))地址進(jìn)行字節(jié)傳送的方式入棧。二是函數(shù)返回值為什么一般放在寄存器中,這主要是為了支持中斷;如果放在堆棧中有可能因為中斷而被覆蓋。三是函數(shù)的返回值如果很大,則從堆棧向存放返回值的地址單元(由主調(diào)函數(shù)在調(diào)用前將此地址壓棧提供給被調(diào)函數(shù))進(jìn)行字節(jié)傳送,以達(dá)到返回的目的。對于第二和第三點,《Thinking in C++》一書在第10章有比較好的闡述。四是一個顯而易見的結(jié)論,如果在被調(diào)函數(shù)中返回局部變量的地址是毫無意義的;因為局部變量存于堆棧中,調(diào)用結(jié)束后堆棧將被清理,這些地址就變得無效了。

三、 C++語言中的函數(shù)參數(shù)傳遞機制

C++既有C的值傳遞又有引用傳遞。在值傳遞上與C一致,這里著重說明引用傳遞。如本文前面所述,引用傳遞就是傳遞變量的地址到被調(diào)函數(shù)使用的堆棧中。在C++中聲明引用傳遞要使用""符號,而調(diào)用時則不用。下面的代碼是使用引用傳遞的swap2函數(shù)和main函數(shù):

int swap2(int x, int y)

{

int temp;

temp = x;

x = y;

y = temp;

return x;

}

void main()

{

int a = 1, b = 2;

swap2(a, b);

}

此時函數(shù)swap2將接受兩個整型變量的地址,同時返回一個其中的一個。而從main函數(shù)中對swap2的調(diào)用swap2(a, b)則看不出是否使用引用傳遞,是否使用引用傳遞,是由swap2函數(shù)的定義決定的。以下是main函數(shù)的匯編代碼:

11: void main()

12: {

……

……

13: int a = 1, b = 2;

00401088 mov dword ptr [ebp-4],1 ;變量a

0040108F mov dword ptr [ebp-8],2 ;變量b

14: swap2(a, b);

00401096 lea eax,[ebp-8] ;將b的偏移地址送入eax

00401099 push eax ;b的偏移地址壓棧

0040109A lea ecx,[ebp-4] ;將a的偏移地址送入ecx

0040109D push ecx ;將a的偏移地址壓棧

0040109E call @ILT+20(swap2) (00401019) ;調(diào)用swap函數(shù)

004010A3 add esp,8 ;清理堆棧中的參數(shù)

15: }

可以看出,main函數(shù)在調(diào)用swap2之前,按照從右至左的順序?qū)和a的偏移地

址壓棧,這就是在傳遞變量的地址。此時swap2函數(shù)的匯編代碼是:

2: int swap2(int x, int y)

3: {

00401030 push ebp

00401031 mov ebp,esp

……

……

4: int temp;

5: temp = x;

00401048 mov eax,dword ptr [ebp+8]

0040104B mov ecx,dword ptr [eax]

0040104D mov dword ptr [ebp-4],ecx

6: x = y;

00401050 mov edx,dword ptr [ebp+8]

00401053 mov eax,dword ptr [ebp+0Ch]

00401056 mov ecx,dword ptr [eax]

00401058 mov dword ptr [edx],ecx

7: y = temp;

0040105A mov edx,dword ptr [ebp+0Ch]

0040105D mov eax,dword ptr [ebp-4]

00401060 mov dword ptr [edx],eax

8: return x;

00401062 mov eax,dword ptr [ebp+8] ;返回x,由于x是外部變量的偏移地

;址,故返回是合法的

9: }

可以看出,swap2與前面的swap函數(shù)的匯編代碼是一樣的。這是因為前面的swap函數(shù)接受指針變量,而指針變量的值正是地址。所以,對于這里的 swap2和前面的swap來講,堆棧中的函數(shù)參數(shù)存放的都是地址,在函數(shù)中操作的方式是一致的。但是,對swap2來說這個地址是主調(diào)函數(shù)通過將實參變量的偏移地址壓棧而傳遞進(jìn)來的--這

是引用傳遞;而對swap來說,這個地址是主調(diào)函數(shù)通過將實參變量的值壓棧而傳遞進(jìn)來的--這是值傳遞,只不過由于這個實參變量是指針變量所以其值是地址而已。

這里的關(guān)鍵點在于,同樣是地址,一個是引用傳遞中的變量地址,一個是值傳遞中的指針變量的值。我想若能明確這一點,就不至于將C語言中的以指針變量作為函數(shù)參數(shù)的值傳遞情況混淆為引用傳遞了。

雖然x是一個局部變量,但是由于其值是主調(diào)函數(shù)中的實參變量的地址,故在swap2中返回這個地址是合法的。

c++ 中經(jīng)常使用的是常量引用,如將swap2改為:

Swap2(const int x; const int y)

這時將不能在函數(shù)中修改引用地址所指向的內(nèi)容,具體來說,x和y將不能出現(xiàn)在"="的左邊。

四、 結(jié)束語

本文論述了在 C 和 c++ 中函數(shù)調(diào)用的參數(shù)傳遞機制;同時附帶說明了函數(shù)返回值的一些問題。本文示例使用的是VC++6.0。

c語言函數(shù)與指針

先學(xué)指針再學(xué)函數(shù)為好。函數(shù)調(diào)用,若想通過參數(shù)帶回函數(shù)運算結(jié)果,要用指針。函數(shù)調(diào)用,若想通過參數(shù)傳入可變大小的數(shù)組,要用指針。 這時若缺乏 指針的知識,則難以學(xué)好函數(shù)的書寫。當(dāng)然,你可以先學(xué)簡單的函數(shù),參數(shù)不用指針的,只通過函數(shù)返回或全局量傳遞運算結(jié)果,只用固定大小的數(shù)組。學(xué)會后,再學(xué)指針和 用指針做參數(shù)的函數(shù)。這樣,路走得慢些,但學(xué)得可能扎實些。

C語言指針函數(shù)和函數(shù)指針詳細(xì)介紹

01

指針函數(shù)通常是指函數(shù)返回值是指針的一類函數(shù),如圖所示。

02

函數(shù)指針是指指向某個具體函數(shù)的指針變量,在程序設(shè)計時可以用來調(diào)用某個特定函數(shù)或者做某個函數(shù)的參數(shù)。其形式一般如圖:

03

指針函數(shù)與函數(shù)指針本質(zhì)上的區(qū)別是,指針函數(shù)是一個帶指針的函數(shù),總的來說還是一個函數(shù),如圖就是一個帶*name指針的函數(shù)

04

函數(shù)指針是指向函數(shù)的指針變量,本質(zhì)上還是一個指針,其格式如下,可以看到和指針函數(shù)的格式非常像,所以一定要用心留意。

C語言:指針函數(shù)跟函數(shù)指針的區(qū)別

本質(zhì)的區(qū)別是:

一個是函數(shù) 一個是指針變量

1、指針函數(shù)是指帶指針的函數(shù),即本質(zhì)是一個函數(shù)。函數(shù)返回類型是某一類型的指針

類型標(biāo)識符 *函數(shù)名(參數(shù)表)

int *f(x,y);

2、函數(shù)指針是指向函數(shù)的指針變量,即本質(zhì)是一個指針變量。

 int (*f) (int x); /* 聲明一個函數(shù)指針 */

 f=func; /* 將func函數(shù)的首地址賦給指針f */

希望對您有所幫助

關(guān)于C語言指針和函數(shù)的問題(追加分)

這么給你解釋吧,指針就相當(dāng)是一個門牌號。第一個呢,是因為f()函數(shù)的參數(shù)是指針,就是“門牌號”,所以他們交換的時候是把門牌號進(jìn)行了交換。所以當(dāng)你第二次進(jìn)行訪問的時候,原來A房間變成了B房間,所以當(dāng)你想要讓A房間里的人出來的時候,這個時候原來住在里面的B君就出來了。所以發(fā)生了交換。

第二個呢,傳的是形參,形參就是把A君復(fù)制一個(我們理解為克隆一個A君),然后克隆一個B君,最后把克隆人交換。然后我們輸出的時候,我們卻要A房間里的人,那個時候,A君還在自己的房間,當(dāng)然他們出來的時候,就是沒有交換了。如果,要交換,我們可以輸出克隆人。那么看到的結(jié)果就是已經(jīng)發(fā)生了交換。

我把第二個代碼,給你稍微改下,就是輸出克隆人,那么你就會看到,我們原來交換的只是克隆人了。

============

第二個

#includestdio.h

void main()

{void f(int x,int y);

int a,b;

scanf("%d,%d",a,b);

f(a,b);

}

void f(int x,int y)

{int p;

p=x;

x=y;

y=p;

printf("%d,%d",x,y);

}

輸入5,9

輸出9,5

===========

有不明白的繼續(xù)追問!


網(wǎng)頁標(biāo)題:c語言中函數(shù)與指針的探討 c語言中指針函數(shù)的用法
轉(zhuǎn)載來于:http://fisionsoft.com.cn/article/hppohp.html