就是一個(gè)函數(shù)的輸入參數(shù)是一個(gè)指針,該函數(shù)需要改變該指針指向的地址,如: 現(xiàn)在有一個(gè)全局?jǐn)?shù)組b,現(xiàn)在需要編寫一個(gè)函數(shù) 輸入?yún)?shù)是一個(gè)指針a,需要通過該函數(shù)將該指針a指向數(shù)組b,即:
intb[3]={1,2,3};
voidfcn(參數(shù));
voidmain()
{
int*a;
fcn(輸入?yún)?shù)a)
}
執(zhí)行完fcn后,使參數(shù)的地址改變,這個(gè)功能怎么來實(shí)現(xiàn)呢?
首先說明結(jié)論:使用二級指針。
為了更好的理解這個(gè)問題,我們首先來學(xué)習(xí)一下指針最經(jīng)典的例子,交換兩個(gè)數(shù)來說明函數(shù)的形參和實(shí)參之間的關(guān)系。
首先來探究以下實(shí)參和形參的關(guān)系是怎樣的。
形參為普通變量類型;
voidtest1(inta,intb)
{
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);//打印形參地址
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);//打印形參值
}
intmain()
{
inta=1,b=2;
printf(">>actualaddra:%d,actualaddrb:%d
",&a,&b);
printf(">>actualvaluea:%d,actualvalueb:%d
",a,b);
test1(a,b);
return0;
}
下面是執(zhí)行結(jié)果:
>>actualaddra:6422300,actualaddrb:6422296
>>actualvaluea:1,actualvalueb:2
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:1,formalvalueb:2
可以看到形參和實(shí)參的值雖然相同,但是他們的地址卻不相同,所以函數(shù)在被調(diào)用的時(shí)候傳入的參數(shù)(實(shí)參)實(shí)際上是被復(fù)制到另一個(gè)地址(形參地址)中去了,函數(shù)中對傳入?yún)?shù)的操作實(shí)際上是對形參地址中的數(shù)進(jìn)行操作,而與實(shí)參無關(guān)。所以下面的函數(shù)不能實(shí)現(xiàn)交換兩個(gè)數(shù)的功能。
voidswap_1(inta,intb)
{
inttemp;
temp=a;
a=b;
b=temp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);
}
intmain()
{
int a = 1, b = 2;
swap_1(a,b);
printf(">>actualaddra:%d,actualaddrb:%d
",&a,&b);
printf(">>actualvaluea:%d,actualvalueb:%d
",a,b);
return0;
}
輸出如下:
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:2,formalvalueb:1
>>actualaddra:6422300,actualaddrb:6422296
>>actualvaluea:1,actualvalueb:2
可以看到在swap_1函數(shù)中a,b兩個(gè)數(shù)的值是被調(diào)換了的,但是函數(shù)中的a,b的地址和主函數(shù)中a,b的地址根本不是同一個(gè),主函數(shù)中a,b還是原來的數(shù),所以這個(gè)函數(shù)起不到交換兩個(gè)數(shù)功能。
既然形參和實(shí)參的關(guān)系是地址不同而值相同那么我們將實(shí)參的地址當(dāng)作參數(shù)傳給形參,然后在函數(shù)中對形參所指向的地址中的值(該地址就是實(shí)參的地址)進(jìn)行改變是否就可以完成兩個(gè)數(shù)的交換了?
OK!下面我們來編寫函數(shù)測試以下:
voidswap_2(int*a,int*b)
{
inttemp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);//打印形參地址
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);//打印形參的值
printf(">>formaladdrvaluea:%d,formaladdrvalueb:%d
",*a,*b);//打印以形參值為地址的值
temp=*a;
*a=*b;
*b=temp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);
printf(">>formaladdrvaluea:%d,formaladdrvalueb:%d
",*a,*b);
}
intmain()
{
inta=1,b=2;
swap_2(&a,&b);
printf(">>actualaddra:%d,actualaddrb:%d
",&a,&b);
printf(">>actualvaluea:%d,actualvalueb:%d
",a,b);
return0;
}
結(jié)果如下:
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:6422300,formalvalueb:6422296
>>formaladdrvaluea:1,formaladdrvalueb:2
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:6422300,formalvalueb:6422296
>>formaladdrvaluea:2,formaladdrvalueb:1
>>actualaddra:6422300,actualaddrb:6422296
>>actualvaluea:2,actualvalueb:1
從結(jié)果可以看出,這個(gè)函數(shù)可以交換輸入?yún)?shù)的值。下面我們來分析一下為什么這個(gè)函數(shù)能夠?qū)崿F(xiàn)交換功能。
以變量a為例,首先,從結(jié)果的第一行可以看出,傳入函數(shù)的參數(shù)是地址(即實(shí)參a的地址:6420300),這個(gè)地址作為一個(gè)值存放在形參a(地址:6422272)中,然后定義一個(gè)int型變量來存放地址6422272(形參a的地址)中的值6422300(實(shí)參a的地址),然后將指向6422296(實(shí)參b的地址)地址中的值 賦給 指向6422300(實(shí)參a的地址),開始地址6422300地址中的值為2,現(xiàn)在該地址的值變?yōu)?,同理,在執(zhí)行函數(shù)之后地址6422296中的值變?yōu)?,從而實(shí)現(xiàn)了兩個(gè)數(shù)的交換。
在這個(gè)過程中,是函數(shù)調(diào)用a,b兩個(gè)值的地址,并在函數(shù)中改變這兩地址中的值。與上一個(gè)函數(shù)的本質(zhì)區(qū)別就是:上一個(gè)函數(shù)swap1只是將a,b的值給復(fù)制到兩個(gè)新的地址當(dāng)中,并改變新的地址中的值,與a,b地址無關(guān)。而swap_2則是直接操作a,b地址中的值,進(jìn)而可以實(shí)現(xiàn)交換兩個(gè)數(shù)的功能。
注意:實(shí)參和形參是在兩個(gè)不同地址,雖然起的名字是一樣的,當(dāng)然這個(gè)名字可以自己隨意起。為了更加清楚的說明實(shí)參和形參是兩個(gè)東西,下面我將形參的變量名給改一下:
voidswap_2(int*formal_a,int*formal_b)
{
inttemp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);
printf(">>formaladdrvaluea:%d,formaladdrvalueb:%d
",*a,*b);
temp=*formal_a;
*formal_a=*formal_b;
*formal_b=temp;
printf(">>formaladdra:%d,formaladdrb:%d
",&a,&b);
printf(">>formalvaluea:%d,formalvalueb:%d
",a,b);
printf(">>formaladdrvaluea:%d,formaladdrvalueb:%d
",*a,*b);
}
intmain()
{
inta=1,b=2;
swap_2(&a,&b);
printf(">>actualaddra:%d,actualaddrb:%d
",&a,&b);
printf(">>actualvaluea:%d,actualvalueb:%d
",a,b);
return0;
}
結(jié)果如下:
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:6422300,formalvalueb:6422296
>>formaladdrvaluea:1,formaladdrvalueb:2
>>formaladdra:6422272,formaladdrb:6422276
>>formalvaluea:6422300,formalvalueb:6422296
>>formaladdrvaluea:2,formaladdrvalueb:1
>>actualaddra:6422300,actualaddrb:6422296
>>actualvaluea:2,actualvalueb:1
和之前的結(jié)果一樣,可以知道,函數(shù)在執(zhí)行的時(shí)候其實(shí)是不管你名字怎么起的,而是關(guān)心地址,而你起的名字實(shí)際也只是那個(gè)地址的代號而已。
通過上面的例子已經(jīng)清楚了函數(shù)的形參與實(shí)參的區(qū)別,那么現(xiàn)在就來解決文章開頭提出的問題
如何通過函數(shù)改變一個(gè)傳入指針作為實(shí)參的地址,其實(shí)在理解上面的關(guān)于函數(shù)的形參和實(shí)參就非常容易懂了。
首先我們來看下面一個(gè)例子
intb[3]={1,2,3};
voidfcn(int**a)
{
*a=b;
}
intmain()
{
unsignedinti=0;
int*a;
for(i=0;i<3;i++)
?????{
?????????printf(">>%d
",a[i]);
}
fcn(&a);
for(i=0;i<3;i++)
?????{
?????????printf(">>%d
",a[i]);
}
}
函數(shù)輸出為:
>>0
>>-1
>>4194304
>>1
>>2
>>3
主函數(shù)中,我們定義了一個(gè)指針a,并且沒有初始化它,之后我們是不能夠直接對它指向的地址進(jìn)行賦值,因?yàn)楝F(xiàn)在它的地址是隨機(jī)的,對該地址進(jìn)行操作后有可能會(huì)導(dǎo)致程序崩潰。我們想要用它就只能夠?qū)λ约旱闹狄簿褪撬赶虻牡刂愤M(jìn)行操作。函數(shù)fcn通過形參來改變輸入實(shí)參的值是怎么做到的呢?
首先看函數(shù)的形參(int **a)
,表示什么意思呢?就是說傳入的一個(gè)二級指針,指向指針的指針,這又是什么意思呢?比如你有一張藏寶圖,它說寶藏在a地,你到a地之后也只得到一張藏寶圖,該藏寶圖說寶藏在b地,你只有到達(dá)b地才能夠得到寶藏。這就是一個(gè)二級指針,第一個(gè)指向的地址是a,a的內(nèi)容也是一個(gè)指針,指向b,b地址下才是真正的內(nèi)容。
我們在主函數(shù)中定義了一個(gè)指針a,讓它傳入函數(shù)fcn,我們分析一下這個(gè)過程:
函數(shù)開辟一個(gè)形參的地址,該地址中的內(nèi)容為指向傳入?yún)?shù)地址的值,那么函數(shù)中我們將數(shù)組b的首地址賦給該地址,也就是將實(shí)參的地址更改成了數(shù)組b的首地址。
文章確實(shí)太繞了,個(gè)人覺得最主要的點(diǎn)就是弄清楚指針與地址以及該地址的值的關(guān)系,還有就是形參與實(shí)參的關(guān)系。
-
C語言
+關(guān)注
關(guān)注
180文章
7605瀏覽量
137000 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4333瀏覽量
62696 -
指針
+關(guān)注
關(guān)注
1文章
480瀏覽量
70576
原文標(biāo)題:C語言指針作為形參如何改變其指向的地址?
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論