91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語言函數(shù)參數(shù)關(guān)于傳值和傳指針有什么區(qū)別?

黃工的嵌入式技術(shù)圈 ? 來源:編程珠璣 ? 作者:守望先生 ? 2020-02-26 16:35 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

函數(shù)傳參有三種傳參方式:傳值、傳址、傳引用。

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

傳值

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

#include voidswap(inta,intb) { inttemp=a; a=b; b=temp; printf("swapa=%d,b=%d\n",a,b); } intmain(void) { inta=10; intb=20; printf("beforeswap:a=%d,b=%d\n",a,b); swap(a,b); printf("afterswap:a=%d,b=%d\n",a,b); return0; }

運行結(jié)果如下:

beforeswap:a=10,b=20 internalswapa=20,b=10 afterswap: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ù)前后的情形如下:

調(diào)用swap前后

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

傳指針

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

#include voidswap(int*a,int*b) { inttemp=*a; *a=*b; *b=temp; printf("swapa=%d,b=%d\n",*a,*b); } intmain(void) { inta=10; intb=20; printf("beforeswap:a=%d,b=%d\n",a,b); swap(&a,&b); printf("afterswap:a=%d,b=%d\n",a,b); return0; }

運行結(jié)果:

beforeswap:a=10,b=20 swapa=20,b=10 afterswap: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 #include voidgetMemery(int*p) { /*申請1024個int大小*/ p=malloc(sizeof(int)*1024); if(NULL==p) { printf("mallocfailed\n"); p=NULL; } } intmain(void) { int*p=NULL; getMemery(p); printf("addressofpis%p\n",p); return0; }

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

addressofpis(nil)

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

getMemory

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

#include #include voidgetMemery(int**p) { /*申請1024個int大小*/ *p=malloc(sizeof(int)*1024); if(NULL==*p) { printf("mallocfailed\n"); *p=NULL; } } intmain(void) { int*p=NULL; getMemery(&p); printf("addressofpis%p\n",p); free(p); p=NULL; return0; }

運行結(jié)果如下:

addressofpis0x144f010

從運行結(jié)果可以看到,p的值被改變了,而不再是初始的NULL。

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

getMemory

總結(jié)

本文總結(jié)如下:

函數(shù)的參數(shù)都是原數(shù)據(jù)的“副本”,因此在函數(shù)內(nèi)無法改變原數(shù)據(jù)

函數(shù)中參數(shù)都是傳值,傳指針本質(zhì)上也是傳值

如果想要改變?nèi)雲(yún)?nèi)容,則需要傳該入?yún)⒌牡刂罚ㄖ羔樅鸵枚际穷愃频淖饔茫?,通過解引用修改其指向的內(nèi)容

以上結(jié)論不限于C語言

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C語言
    +關(guān)注

    關(guān)注

    183

    文章

    7644

    瀏覽量

    145544
  • SWAP
    +關(guān)注

    關(guān)注

    0

    文章

    52

    瀏覽量

    13678
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4417

    瀏覽量

    67494
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    傳遞一個無符號的 long 型指針函數(shù)

    C語言允許傳遞指針函數(shù),只需要簡單地聲明函數(shù)參數(shù)指針
    發(fā)表于 01-27 11:51

    指針函數(shù)詳解

    = a + b; return(p); } 這是一個簡單的指針函數(shù)的例子,運行結(jié)果如下,本文代碼在VScode平臺運行,使用方法《使用VScode調(diào)試C語言》。 不過我
    發(fā)表于 01-23 06:02

    函數(shù)指針介紹

    :類型說明符 (*函數(shù)名) (參數(shù)) int (*fun)(int x,int y); 函數(shù)指針是需要把一個函數(shù)的地址賦值給它,
    發(fā)表于 01-21 08:11

    函數(shù)指針與回調(diào)函數(shù)解讀

    函數(shù)指針是指向函數(shù)指針變量。通過函數(shù)指針C
    發(fā)表于 01-19 07:34

    C語言函數(shù)指針的六個高級的應(yīng)用場景

    ; } 在上面的代碼中,我們定義了一個 handle_event 函數(shù),它接受兩個參數(shù):一個事件類型和一個函數(shù)指針。如果函數(shù)
    發(fā)表于 01-04 12:25

    C語言回調(diào)函數(shù)原來這么簡單

    ” 這個概念,它是回調(diào)函數(shù)能夠?qū)崿F(xiàn)的重要基礎(chǔ)。 1、函數(shù)指針學(xué)習(xí)過C語言的伙伴都知道,C
    發(fā)表于 12-30 06:45

    如何用好 C 語言函數(shù)的返回?

    潛規(guī)則”更好一點。 仔細考慮下,其實C語言函數(shù)使用返回 0 表示成功是原因的。更一般的C
    發(fā)表于 12-25 07:17

    C語言C++的區(qū)別及聯(lián)系

    創(chuàng)建源文件時什么都不給,默認是.cpp。 3、返回 C語言中,如果一個函數(shù)沒有指定返回類型,默認返回int類型;
    發(fā)表于 12-24 07:23

    函數(shù)指針指針函數(shù)區(qū)別

    指針函數(shù),即本質(zhì)是一個函數(shù)函數(shù)返回類型是某一類型的指針   類型標(biāo)識符 *函數(shù)名(
    發(fā)表于 12-12 06:34

    函數(shù)指針的概念

    函數(shù)返回類型 (* 指針變量名) (函數(shù)參數(shù)列表); “函數(shù)返回
    發(fā)表于 12-11 08:10

    如何用函數(shù)指針調(diào)用函數(shù)

    p*/ p =Func; /*將Func函數(shù)的首地址賦給指針變量p*/ 賦值時函數(shù) Func 不帶括號,也不帶參數(shù)。由于函數(shù)名 Fun
    發(fā)表于 12-11 06:26

    科普|無線圖和寬帶自組網(wǎng)什么區(qū)別?

    這兩個設(shè)備到底哪些區(qū)別。其實無線圖和寬帶自組網(wǎng)設(shè)備在一些技術(shù)上是相通的,應(yīng)用也有部分重疊,但是整體的技術(shù)原理和應(yīng)用場景上上還是很大差別的。無線圖
    的頭像 發(fā)表于 08-15 17:44 ?1056次閱讀
    科普|無線圖<b class='flag-5'>傳</b>和寬帶自組網(wǎng)<b class='flag-5'>有</b><b class='flag-5'>什么區(qū)別</b>?

    CY7C65214和CY7C65211/3/5什么區(qū)別?

    CY7C65214 和其他 USB 串行橋接控制器之間什么區(qū)別:CY7C65211、CY7C65213 和 CY7
    發(fā)表于 05-29 06:49

    GD32與STM32什么區(qū)別

    電子發(fā)燒友網(wǎng)站提供《GD32與STM32什么區(qū)別.docx》資料免費下載
    發(fā)表于 04-03 17:27 ?0次下載

    關(guān)于STM32 CAN通信發(fā)送函數(shù)HAL_CAN_AddTxMessage()的最后一個參數(shù)填0和定義一個變量取地址的問題求解

    問題: 關(guān)于STM32 CAN通信 發(fā)送函數(shù) HAL_CAN_AddTxMessage()的最后一個參數(shù)填0和定義一個變量取地址的問題,如果直接0,我實驗發(fā)現(xiàn) STM32F103
    發(fā)表于 03-11 08:22