你知道C語(yǔ)言函數(shù)調(diào)用常用的2種方式嗎
本篇博客會(huì)講解C語(yǔ)言函數(shù)調(diào)用的2種方式,分別是:傳值調(diào)用和傳址調(diào)用。這2種函數(shù)調(diào)用方式有什么區(qū)別呢?為什么會(huì)有不同的效果呢?分別有哪些用途呢?下面我會(huì)一一展開(kāi)。
區(qū)別
傳值調(diào)用,即通過(guò)傳遞變量的值來(lái)調(diào)用函數(shù)。
傳址調(diào)用,即通過(guò)傳遞變量的地址來(lái)調(diào)用函數(shù)。
比如,假設(shè)有2個(gè)變量a和b,對(duì)于變量a和b來(lái)說(shuō),test(a, b)就是傳值調(diào)用,test(&a, &b)就是傳址調(diào)用。
原理
這時(shí)你可能很好奇:這2種調(diào)用方式的原理是什么呢?其實(shí)非常簡(jiǎn)單。
先舉個(gè)傳值調(diào)用的例子:
// 函數(shù)定義
int Add(int x, int y)
{
return x + y;
}
// 調(diào)用
int a = 3, b = 5;
int sum = Add(a, b);在上面的代碼中,我們分別把a(bǔ)和b的值傳遞給了Add函數(shù)中的x和y。此時(shí),我們稱:a和b是“實(shí)際參數(shù)”,簡(jiǎn)稱實(shí)參;x和y是“形式參數(shù)”,簡(jiǎn)稱形參。傳值調(diào)用的方式,會(huì)把實(shí)參的值傳遞給形參,也就是說(shuō),把a(bǔ)中的3傳遞給x,此時(shí)x就是3,把b中的5傳遞給y,此時(shí)y就是5。在Add函數(shù)內(nèi)部,把x+y的值帶回來(lái),也就返回3+5的值,即返回8,再把返回值賦值給sum,sum就是8。
再舉個(gè)傳址調(diào)用的例子:
// 函數(shù)定義
int Add(int* p1, int* p2)
{
return *p1 + *p2;
}
// 調(diào)用
int a = 3, b = 5;
int sum = Add(&a, &b);以上就是典型的傳址調(diào)用,但是很顯然在這個(gè)場(chǎng)景下,我們只想“求和”,使用傳址調(diào)用有點(diǎn)多此一舉,但是還是分析一下原理:我們把a(bǔ)和b的地址傳給了p1和p2,此時(shí)p1存儲(chǔ)了a的地址,p2存儲(chǔ)了b的地址,p1就指向了a,p2就指向了b。我們想在Add函數(shù)內(nèi)部求和,就要先對(duì)p1解引用,拿到a的值,再對(duì)p2解引用,拿到b的值,再把拿到的a和b的值加起來(lái)返回,此時(shí)sum就被賦值為函數(shù)的返回值,即8。
以上只是非常粗略的帶大家了解了傳值調(diào)用和傳址調(diào)用的區(qū)別。下面用一個(gè)經(jīng)典的例子進(jìn)行更加深入的講解。這個(gè)例子就是:寫(xiě)一個(gè)函數(shù),交換2個(gè)整數(shù)的值。
使用傳值調(diào)用的方式,寫(xiě)出來(lái)的函數(shù)如下:
// 定義
void Swap(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
// 調(diào)用
int a = 3, b = 5;
Swap(a, b);
下面我通過(guò)調(diào)試的方式,來(lái)帶大家看一下這個(gè)程序會(huì)如何執(zhí)行。

代碼即將執(zhí)行Swap(a, b);,此時(shí)a的值是3,b的值是5。接下來(lái)執(zhí)行這條語(yǔ)句:

代碼來(lái)到第17行,此時(shí)a和b的值并沒(méi)有交換?到底發(fā)生了啥?
重新開(kāi)始調(diào)試,這次我進(jìn)入到Swap函數(shù)內(nèi)部看一眼。

按照前面的分析,此時(shí)x和y拿到了a和b的值,接下來(lái)進(jìn)行交換:

代碼執(zhí)行到第10行,此時(shí)可以發(fā)現(xiàn),x和y其實(shí)已經(jīng)交換了,但是a和b并沒(méi)有變化?這又是為什么呢?
此時(shí)再回到main函數(shù),發(fā)現(xiàn)a和b的值并沒(méi)有被交換。

發(fā)現(xiàn)這個(gè)問(wèn)題后,我們可以干一件事,使用下面的代碼,把a(bǔ)、b、x、y的地址打印出來(lái):
#include <stdio.h>
void Swap(int x, int y)
{
printf("&x = %p, &y = %p\n", &x, &y);
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 3, b = 5;
printf("&a = %p, &b = %p\n", &a, &b);
Swap(a, b);
return 0;
}輸出結(jié)果如下:

可以發(fā)現(xiàn),當(dāng)把a(bǔ)的值傳遞給x,把b的值傳遞給y時(shí),x和y,a和b已經(jīng)是不同的空間了,此時(shí)相當(dāng)于,內(nèi)存中有4個(gè)變量,分別是a、b、x、y,由于值傳遞,x的值和a相同,y的值和b相同,此時(shí)交換了x和y,對(duì)a和b的值并沒(méi)有影響!所以函數(shù)調(diào)用結(jié)束后,a和b的值并沒(méi)有交換。
這時(shí),我們就可以總結(jié):當(dāng)我們使用傳值調(diào)用,實(shí)參的值傳遞給形參后,形參只是實(shí)參的一份臨時(shí)拷貝,改變形參的值并不影響實(shí)參的值!
那Swap函數(shù)的正確實(shí)現(xiàn)形式是怎樣的呢?相信聰明的你已經(jīng)想到了,使用傳址調(diào)用就行了嘛!
// 定義
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
// 調(diào)用
int a = 3, b = 5;
Swap(&a, &b);為什么以上的代碼就能實(shí)現(xiàn)“交換”的效果呢?這就是傳址調(diào)用的神奇之處!
分析一下:把a(bǔ)的地址傳遞給p1,把b的地址傳遞給p2,此時(shí)p1就指向了a,p2就指向了b,這時(shí)再對(duì)p1和p2解引用,就能把a(bǔ)和b的值給修改了!
我們還是通過(guò)調(diào)試來(lái)觀察一下細(xì)節(jié):

進(jìn)入到函數(shù)內(nèi)部:

再回到main函數(shù):

成功交換了a和b的值!
用途
根據(jù)以上的講解,可以總結(jié)一下傳值調(diào)用和傳址調(diào)用的用途:
- 傳值調(diào)用適用于不需要修改函數(shù)外部變量的場(chǎng)景。
- 傳址調(diào)用適用于需要修改函數(shù)外部變量的場(chǎng)景。
這是因?yàn)?,傳值調(diào)用時(shí),形參是實(shí)參的一份臨時(shí)拷貝,改變形參并不影響實(shí)參,所以在函數(shù)內(nèi)部沒(méi)有能力改變外面的變量的值;傳址調(diào)用就不一樣了,形參保存了函數(shù)外部變量的地址,就可以通過(guò)解引用的方式,修改函數(shù)外部變量的值了。
總結(jié)
1.傳值調(diào)用適用于不需要修改函數(shù)外部變量的場(chǎng)景,因?yàn)楹瘮?shù)內(nèi)部變量和外部變量并沒(méi)有建立聯(lián)系,是獨(dú)立的空間。
2.傳址調(diào)用適用于需要修改函數(shù)外部變量的場(chǎng)景,因?yàn)楹瘮?shù)內(nèi)部存儲(chǔ)了指向函數(shù)外部變量的指針,建立了聯(lián)系,可以通過(guò)解引用的方式改變函數(shù)外部的變量。
以上就是你知道C語(yǔ)言函數(shù)調(diào)用常用的2種方式嗎的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言函數(shù)調(diào)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C/C++ 實(shí)現(xiàn)遞歸和棧逆序字符串的實(shí)例
這篇文章主要介紹了C/C++ 實(shí)現(xiàn)遞歸和棧逆序字符串的實(shí)例的相關(guān)資料,這里提供實(shí)例代碼幫助大家學(xué)習(xí)掌握,需要的朋友可以參考下2017-08-08
用C語(yǔ)言簡(jiǎn)單實(shí)現(xiàn)掃雷小游戲
這篇文章主要為大家詳細(xì)介紹了用C語(yǔ)言簡(jiǎn)單實(shí)現(xiàn)掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
C語(yǔ)言鏈表實(shí)現(xiàn)商品庫(kù)存管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言鏈表實(shí)現(xiàn)商品庫(kù)存管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
C語(yǔ)言基礎(chǔ)之格式化輸出控制長(zhǎng)度
這篇文章主要介紹了C語(yǔ)言基礎(chǔ)之格式化輸出控制長(zhǎng)度的相關(guān)資料,需要的朋友可以參考下2017-04-04

