国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C > 正文

C語言中傳值與傳指針的介紹與區(qū)別

2020-01-26 13:26:25
字體:
供稿:網(wǎng)友

前言

我們可能聽過C語言中的傳值和傳指針,在其他語言中,也有傳引用一說,那么他們到底有什么區(qū)別呢?如果你還不能準確地分辨,就該好好了解一下了。

傳值

我們在初學(xué)C語言的時候就被老師教過,下面的方式是無法交換a和b的值的:

#include<stdio.h>void swap(int a,int b){ int temp = a; a = b; b = temp; printf("swap a = %d,b = %d/n",a,b);}int main(void){ int a = 10; int b = 20; printf("before swap:a = %d,b = %d/n",a,b); swap(a,b); printf("after swap:a = %d,b = %d/n",a,b); return 0;}

運行結(jié)果如下:

before swap:a = 10,b = 20                                                                                                                                                                  
internal swap a = 20,b = 10                                                                                                                                                                
after  swap:a = 10,b = 20

可以看到,a和b的值最終并沒有被交換。開始時a,b的值為10,20,而最終還是同樣的值。

為什么呢?因為函數(shù)參數(shù)在傳遞的時候,都是傳原數(shù)據(jù)的副本,也就是說,swap內(nèi)部使用的a和b只是最初始a和b的一個副本而已,所以無論在swap函數(shù)內(nèi)部對a和b做任何改變,都不會影響初始的a和b的值。

正因如此,我們常常被告知,不要把直接把結(jié)構(gòu)體直接作為參數(shù),這樣效率會很低。由于結(jié)構(gòu)體本身占用字節(jié)數(shù)較大,如果直接作為參數(shù),那么將會產(chǎn)生一個較大的”副本“,如此一來,效率也就很低了。

我們再結(jié)合下面的圖來理解:

首先圖中方框中的上部分a和b代表了main函數(shù)中的a和b,即原始數(shù)據(jù),而方框中的下部分a和b代表了函數(shù)的參數(shù)a和b,即原始數(shù)據(jù)的“副本”。(后面的圖都是如此,上部分代表原始值,下部分代表函數(shù)參數(shù)值)。

調(diào)用swap函數(shù)前后的情形如下:

由于在swap中永遠只是對a和b的副本進行操作,因此完全不影響原始的a和b的值。最終也不可能達到交換a和b的值的目的。

傳指針

那么為解決上面的問題,我們知道,需要傳指針。其代碼如下:

#include<stdio.h>void swap(int *a,int *b){ int temp = *a; *a = *b; *b = temp; printf("swap a = %d,b = %d/n",*a,*b);}int main(void){ int a = 10; int b = 20; printf("before swap:a = %d,b = %d/n",a,b); swap(&a,&b); printf("after swap:a = %d,b = %d/n",a,b); return 0;}

運行結(jié)果:

before swap:a = 10,b = 20                                                                                                                                                                  
swap a = 20,b = 10                                                                                                                                                                         
after  swap:a = 20,b = 10

可以看到在這種情況下,a,b的值才是真正交換了。

為什么又有傳值,又有傳指針

看到這里,不知道你是否會疑惑,為什么給函數(shù)傳遞參數(shù)的時候,一會是傳值,一會是傳指針呢?為什么傳指針就能改變參數(shù)的值呢?實際上,C語言里,參數(shù)傳遞都是值傳遞!也就是說,你認為的傳指針也是傳值,只不過它的值是指針類型罷了。

我們再通過圖來理解前面為什么傳指針就可以交換a,b的值:

從圖中可以看出,雖然傳遞給函數(shù)的是指向a和b的指針的副本,但是它的副本同樣也是指向a和b,因此雖然不能改變指針的指向,但是能改變參數(shù)a和b指向的內(nèi)容,即改變原始a和b的值。

再看傳指針

如果是為指針p申請一段內(nèi)存,下面的代碼能達到目的嗎?

#include<stdio.h>#include<stdlib.h>void getMemery(int *p){ /*申請1024個int大小*/ p = malloc(sizeof(int)*1024); if(NULL == p) { printf("malloc failed/n"); p = NULL; }}int main(void){ int *p = NULL; getMemery(p); printf("address of p is %p/n",p); return 0;}

通過前面的內(nèi)容分析,肯定是達不到預(yù)期效果的。

 運行結(jié)果:

address of p is (nil)

這是為什么呢?我們還是利用前面所知來分析,由于傳遞給getMemory函數(shù)的參數(shù)都是一個副本,因此函數(shù)內(nèi)的p也是外部p的一個副本,因此即便在函數(shù)內(nèi)部,將p指向了一塊新申請的內(nèi)存,仍然不會改變外面p的值,即p還是指向NULL。

如何修改呢?我們需要傳入p的地址,即指向int類型指針的指針。

#include<stdio.h>#include<stdlib.h>void getMemery(int **p){ /*申請1024個int大小*/ *p = malloc(sizeof(int)*1024); if(NULL == *p) { printf("malloc failed/n"); *p = NULL; }}int main(void){ int *p = NULL; getMemery(&p); printf("address of p is %p/n",p); free(p); p = NULL; return 0;}

運行結(jié)果如下:

address of p is 0x144f010

從運行結(jié)果可以看到,p的值被改變了。

可配合下面的圖進行理解:

總結(jié)

本文總結(jié)如下:

  • 函數(shù)的形參都是原數(shù)據(jù)的“副本”,因此在函數(shù)內(nèi)無法改變原數(shù)據(jù)
  • 函數(shù)中參數(shù)都是傳值,傳指針本質(zhì)上也是傳值
  • 如果想要改變?nèi)雲(yún)?nèi)容,則需要傳該入?yún)⒌牡刂罚ㄖ羔樅鸵枚际穷愃频淖饔茫ㄟ^解引用修改其指向的內(nèi)容
  • 以上結(jié)論不限于C語言

思考

  • 如何實現(xiàn)不借助第三個變量,交換兩個整數(shù)的值?
  • 結(jié)合本文,理解C++/Java中所謂的傳引用

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對武林網(wǎng)的支持。

本文作者: 守望

本文鏈接: https://www.yanbinghu.com/2019/06/20/53981.html

版權(quán)聲明: 本文為原創(chuàng)文章,版權(quán)歸守望所有,并采用 CC BY-NC-SA 3.0 許可協(xié)議。轉(zhuǎn)載請聯(lián)系本人!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 亚东县| 古交市| 乐至县| 阜康市| 新建县| 扶余县| 英吉沙县| 奉贤区| 丰城市| 耿马| 大丰市| 会理县| 奎屯市| 新和县| 灵寿县| 灵台县| 宁河县| 任丘市| 景宁| 石景山区| 乳山市| 庄河市| 辽宁省| 平江县| 泗洪县| 博湖县| 怀柔区| 民乐县| 泌阳县| 手游| 梧州市| 华蓥市| 滦平县| 武山县| 墨竹工卡县| 德州市| 白河县| 舒城县| 康马县| 堆龙德庆县| 江山市|