欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2019年06月23日 09:57:59   作者:守望  
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中傳值與傳指針的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C語(yǔ)言具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

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

傳值

我們?cè)诔鯇W(xué)C語(yǔ)言的時(shí)候就被老師教過,下面的方式是無法交換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;
}

運(yùn)行結(jié)果如下:

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

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

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

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

我們?cè)俳Y(jié)合下面的圖來理解:

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

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

由于在swap中永遠(yuǎn)只是對(duì)a和b的副本進(jìn)行操作,因此完全不影響原始的a和b的值。最終也不可能達(dá)到交換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;
}

運(yùn)行結(jié)果:

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

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

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

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

我們?cè)偻ㄟ^圖來理解前面為什么傳指針就可以交換a,b的值:

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

再看傳指針

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

#include<stdio.h>
#include<stdlib.h>
void getMemery(int *p)
{
 /*申請(qǐng)1024個(gè)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)容分析,肯定是達(dá)不到預(yù)期效果的。

 運(yùn)行結(jié)果:

address of p is (nil)

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

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

#include<stdio.h>
#include<stdlib.h>
void getMemery(int **p)
{
 /*申請(qǐng)1024個(gè)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;
}

運(yùn)行結(jié)果如下:

address of p is 0x144f010

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

可配合下面的圖進(jìn)行理解:

總結(jié)

本文總結(jié)如下:

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

思考

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

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

本文作者: 守望

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

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

相關(guān)文章

  • C語(yǔ)言入門篇--理解地址及內(nèi)存

    C語(yǔ)言入門篇--理解地址及內(nèi)存

    本篇文章是基礎(chǔ)篇,適合c語(yǔ)言剛?cè)腴T的朋友,本文主要介紹了c語(yǔ)言的內(nèi)存及地址,幫助大家快速入門c語(yǔ)言的世界,更好的理解c語(yǔ)言
    2021-08-08
  • 淺析C語(yǔ)言中sscanf 的用法

    淺析C語(yǔ)言中sscanf 的用法

    以下是對(duì)C語(yǔ)言中sscanf函數(shù)的使用方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07
  • 一篇文章讓你徹底明白c++11增加的變參數(shù)模板

    一篇文章讓你徹底明白c++11增加的變參數(shù)模板

    C++11的新特性--可變模版參數(shù)(variadic templates)是C++11新增的最強(qiáng)大的特性之一,它對(duì)參數(shù)進(jìn)行了高度泛化,它能表示0到任意個(gè)數(shù)、任意類型的參數(shù),這篇文章主要給大家詳細(xì)介紹了關(guān)于c++11增加的變參數(shù)模板的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • c++ using定義類型別名的具體使用

    c++ using定義類型別名的具體使用

    本文主要介紹了c++ using定義類型別名的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • C++基于文件流與armadillo讀取mnist示例詳解

    C++基于文件流與armadillo讀取mnist示例詳解

    這篇文章主要給大家介紹了關(guān)于C++基于文件流與armadillo讀取mnist的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 利用C語(yǔ)言結(jié)構(gòu)體實(shí)現(xiàn)通訊錄

    利用C語(yǔ)言結(jié)構(gòu)體實(shí)現(xiàn)通訊錄

    這篇文章主要為大家詳細(xì)介紹了利用C語(yǔ)言結(jié)構(gòu)體實(shí)現(xiàn)通訊錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 利用C語(yǔ)言繪制一個(gè)正方體

    利用C語(yǔ)言繪制一個(gè)正方體

    這篇文章主要為大家詳細(xì)介紹了如何利用C語(yǔ)言繪制一個(gè)正方體,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)和借鑒價(jià)值,感興趣的小伙伴可以學(xué)習(xí)一下
    2023-01-01
  • C++實(shí)現(xiàn)學(xué)生管理系統(tǒng)示例解析

    C++實(shí)現(xiàn)學(xué)生管理系統(tǒng)示例解析

    這篇文章主要介紹了C++實(shí)現(xiàn)學(xué)生管理系統(tǒng)示例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • C++面向?qū)ο蠖嗉?jí)菜單向Arduino的移植問題小結(jié)

    C++面向?qū)ο蠖嗉?jí)菜單向Arduino的移植問題小結(jié)

    這篇文章主要介紹了C++面向?qū)ο蠖嗉?jí)菜單向Arduino的移植問題及實(shí)現(xiàn)思路,本文通過示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • 使用Clion刷LeetCode的方法

    使用Clion刷LeetCode的方法

    這篇文章主要介紹了使用Clion刷LeetCode的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02

最新評(píng)論