最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言中的參數(shù)傳遞機(jī)制詳解

 更新時(shí)間:2017年04月05日 08:51:24   作者:zhiheng  
這篇文章主要介紹了C語(yǔ)言中的參數(shù)傳遞機(jī)制,C語(yǔ)言中函數(shù)參數(shù)的傳遞有:值傳遞、地址傳遞、引用傳遞這三種形式。下面我們?cè)敿?xì)探討下

C中的參數(shù)傳遞

本文嘗試討論下C中實(shí)參與形參的關(guān)系,即參數(shù)傳遞的問(wèn)題。

C語(yǔ)言的參數(shù)傳遞

值傳遞

首先看下列代碼:

#include <stdio.h>
 
int main(){
  int n = 1;
  printf("實(shí)參n的值:%d,地址:%#x\n", n, &n);
  void change(int i);//函數(shù)聲明
  change(n);
  printf("函數(shù)調(diào)用后實(shí)參n的值:%d,地址:%#x\n", n, &n);
  return 0;
}
 
void change(int i){
  printf("形參i的值:%d,地址:%#x\n",i,&i);
  i++;
  printf("自增操作后形參i的值:%d,地址:%#x\n",i,&i);
}
 

編譯后執(zhí)行結(jié)果如下:

實(shí)參n的值:1,地址:0x5fcb0c
形參i的值:1,地址:0x5fcae0
自增操作后形參i的值:2,地址:0x5fcae0
函數(shù)調(diào)用后實(shí)參n的值:1,地址:0x5fcb0c
 

可以看到,在調(diào)用函數(shù) change 時(shí),會(huì)在內(nèi)存中單獨(dú)開(kāi)辟一個(gè)空間用于存放形式參數(shù) i ,實(shí)參 n 的值會(huì)復(fù)制給形參 i 。對(duì)于形參的任何操作都不會(huì)影響到主調(diào)函數(shù)中的實(shí)參 n 。這種參數(shù)傳遞方式是便是典型的值傳遞。

上例中的參數(shù)類(lèi)型是int型,實(shí)際上,對(duì)于整形(int、short、long、long long)、浮點(diǎn)型(float、double、long double)、字符型(char)等基本類(lèi)型的參數(shù)都是值傳遞。

指針參數(shù)

在下面的例子中,函數(shù)的參數(shù)類(lèi)型是一個(gè)指針:

#include <stdio.h>
 
void change(int * i){
  printf("形參i的值:%#x,地址:%#x\n",i,&i);
  (*i)++;//通過(guò)指針修改其所指空間的值
  i++;//讓指針指向下一塊內(nèi)存空間
  printf("自增操作后形參i的值:%#x,地址:%#x\n",i,&i);
}
 
int main(){
  int n = 1;
  int * p = &n;
  printf("n的值:%d,地址:%#x\n", n, &n);
  printf("實(shí)參p的值:%#x,地址:%#x\n", p, &p);
  change(p);
  printf("函數(shù)調(diào)用后實(shí)參p的值:%#x,地址:%#x\n", p, &p);
  printf("函數(shù)調(diào)用后n的值:%d,地址:%#x\n", n, &n);
  return 0;
}
 

編譯后執(zhí)行結(jié)果如下:

n的值:1,地址:0x5fcb0c
實(shí)參p的值:0x5fcb0c,地址:0x5fcb00
形參i的值:0x5fcb0c,地址:0x5fcae0
自增操作后形參i的值:0x5fcb10,地址:0x5fcae0
函數(shù)調(diào)用后實(shí)參p的值:0x5fcb0c,地址:0x5fcb00
函數(shù)調(diào)用后n的值:2,地址:0x5fcb0c
 

指針是C語(yǔ)言中的一種特殊類(lèi)型,它本身占用一定的內(nèi)存空間,而存儲(chǔ)的值卻是某個(gè)內(nèi)存地址。上例中,函數(shù)change的參數(shù)是指向int型變量的指針,實(shí)參p是指向變量n的一個(gè)指針,在調(diào)用函數(shù)change時(shí),指針型的形參i也會(huì)得到一塊內(nèi)存空間,其值由實(shí)參p復(fù)制而來(lái),都是主調(diào)函數(shù)中變量n的地址。對(duì)于指針類(lèi)型,一般不會(huì)太關(guān)注其本身而更多的是考慮它所指向的值,所以,在change函數(shù)內(nèi)是通過(guò)指針來(lái)操作指針?biāo)傅膬?nèi)容(主調(diào)函數(shù)中的變量n)。這樣,便實(shí)現(xiàn)了在被調(diào)函數(shù)內(nèi)操作主調(diào)函數(shù)中數(shù)據(jù)的效果。

雖然通過(guò)指針型參數(shù)傳遞可以達(dá)到讓被調(diào)函數(shù)內(nèi)的操作作用于主調(diào)函數(shù)內(nèi)數(shù)據(jù)的效果,但從實(shí)參和形參的角度來(lái)看,這種參數(shù)傳遞并沒(méi)有和一般的傳遞方法有什么本質(zhì)的區(qū)別,也是值傳遞方式。

當(dāng)參數(shù)傳遞方式是值傳遞時(shí),形參和實(shí)參都存儲(chǔ)在各自的內(nèi)存空間中,相互獨(dú)立互不影響,它們之間唯一的聯(lián)系便是在形參初始化時(shí)會(huì)使用實(shí)參的值。

數(shù)組參數(shù)

在C語(yǔ)言中,數(shù)組名可以看作一個(gè)指向數(shù)組首元素的指針常量,那么當(dāng)數(shù)組作為參數(shù)是又是如何傳遞呢?實(shí)際上,當(dāng)函數(shù)形參是數(shù)組類(lèi)型時(shí),作為形參的數(shù)組名便不再代表數(shù)組,而是被編譯器解析成一個(gè)指針。通過(guò)下面的例子可以看出,數(shù)組類(lèi)型的形參只是在函數(shù)簽名中看上去是一個(gè)數(shù)組,但在函數(shù)體內(nèi),它已經(jīng)徹底淪為一個(gè)指針。

#include <stdio.h>
 
void arrArg(int arr[]){
  printf("形參arr的值:%#x,地址:%#x\n", arr, &arr);
  printf("sizeof(arr):%d, sizeof(int *):%d\n",sizeof(arr), sizeof(int *));
  printf("sizeof(arr[0]):%d,sizeof(int):%d\n", sizeof(arr[0]), sizeof(int));
  printf("*arr:%d,arr[0]:%d\n", *arr, arr[0]);
  printf("*(arr+1):%d,arr[1]:%d\n", *(arr+1), arr[1]);
  printf("arr+1:%#x,&arr[1]:%#x\n",arr+1, &arr[1]);
  arr++;
  printf("自增操作后形參arr的值:%#x,地址:%#x\n",arr, &arr);
  printf("自增操作后,*arr:%d, arr[0]:%d\n",*arr, arr[0]);
}
 
int main(){
  int a[] = {1,2,3};
  printf("實(shí)參a的值:%#x,地址:%#x\n",a,&a);
  printf("sizeof(a):%d,sizeof(a[0]):%d\n",sizeof(a),sizeof(a[0]));
  arrArg(a);
  return 0;
}
 

編譯后執(zhí)行結(jié)果如下:

實(shí)參a的值:0x5fcb00,地址:0x5fcb00
sizeof(a):12,sizeof(a[0]):4
形參arr的值:0x5fcb00,地址:0x5fcae0
sizeof(arr):8, sizeof(int *):8
sizeof(arr[0]):4,sizeof(int):4
*arr:1,arr[0]:1
*(arr+1):2,arr[1]:2
arr+1:0x5fcb04,&arr[1]:0x5fcb04
自增操作后形參arr的值:0x5fcb04,地址:0x5fcae0
自增操作后,*arr:2, arr[0]:2
 

可以看出,雖然形參arr被聲明為int型數(shù)組,但在函數(shù)內(nèi)部,arr已不再擁有數(shù)組的性質(zhì),而擁有了指向int型的指針的性質(zhì):

arr的大小是指針的大?。?),而非數(shù)組的大?。〝?shù)組的大小是所有元素大小的總和,上例中:4×3=12)
arr可以被修改,而數(shù)組名不可以被修改
arr與a的內(nèi)存地址不同但值相同(都是數(shù)組首元素地址),所以,在函數(shù)被調(diào)用時(shí),真正被傳遞的值是數(shù)組首元素的地址,并以此地址初始化了一個(gè)指向?qū)崊?shù)組首元素的指針作為形參。因?yàn)閷?shí)際的形參是一個(gè)指針,所以這種情況也是屬于值傳遞。同時(shí),與指針參數(shù)效果一樣,在函數(shù)內(nèi)對(duì)“數(shù)組”的修改會(huì)直接作用于外部。

由此我們看到,數(shù)組作為參數(shù)與指針作為參數(shù)并沒(méi)有什么區(qū)別,因?yàn)榫幾g器會(huì)自動(dòng)將形參中的數(shù)組名轉(zhuǎn)換為一個(gè)指針。所以,以下面代碼中的兩個(gè)函數(shù)簽名是等效的:

void func(int arr[]){
 
}
void func(int * p){
 
}
 

實(shí)際上,如果我們同時(shí)定義了它們,編譯器會(huì)報(bào)“redefinition”錯(cuò)誤而無(wú)法編譯。

此外需要注意的是,雖然我們可以將形參聲明成一個(gè)數(shù)組,但在編譯器看來(lái)它只是一個(gè)指針而已,因此形參中有關(guān)數(shù)組長(zhǎng)度的信息會(huì)被自動(dòng)忽略,在實(shí)際調(diào)用時(shí)實(shí)參數(shù)組的長(zhǎng)度與形參指定的數(shù)組長(zhǎng)度沒(méi)有任何關(guān)系,而且在函數(shù)內(nèi)也無(wú)法通過(guò) sizeof(arr)/sizeof(arr[0]) 得到數(shù)組的長(zhǎng)度。

//形參arr的指定長(zhǎng)度5無(wú)意義,會(huì)被編譯器忽略,未防止誤解建議不寫(xiě)
void arrArg(int arr[5]){
 // sizeof(arr)是指針類(lèi)型的大小而非數(shù)組大小,因此len不是數(shù)組長(zhǎng)度 
 int len = sizeof(arr)/ sizeof(arr[0]);
}
 

自定義類(lèi)型參數(shù)

數(shù)組這種“組合”類(lèi)型在作為參數(shù)傳遞時(shí)被解析為指針?lè)绞絺鬟f,那么當(dāng)結(jié)構(gòu)體(struct)、共同體(union)以及枚舉類(lèi)型作為參數(shù)傳遞時(shí)是否也是如此呢?

枚舉類(lèi)型本質(zhì)上是int,所以當(dāng)形參被聲明為枚舉類(lèi)型時(shí),在編譯器看來(lái)就是int型,以下面代碼中的兩個(gè)函數(shù)簽名是等效的,編譯器會(huì)報(bào)“redefinition”錯(cuò)誤:

enum week{ Mon, Tues, Wed, Thurs, Fri, Sat, Sun };
 
void func(enum weekday){}
 
void func(int i){}
 

下面是結(jié)構(gòu)體和共同體分別作為參數(shù)時(shí)的示例:

#include <stdio.h>
 
struct Date{
  int year;
  int month;
  int day;
};
 
void changeStruct(struct Datedate){
  printf("形參date的地址:%#x\n", &date);
  date.year ++;
  date.month = 12;
  date.day = 31;
  printf("形參date的值:%d-%d-%d\n",date.year,date.month,date.day);
}
 
union Data{
  int i;
  float f;
  double d;
};
 
void changeUnion(unionDatadata ){
  printf("形參data的地址:%#x\n", &data);
  printf("形參data的值,d.i:%d, d.f:%f, d.d:%f\n",data.i,data.f,data.d);
  data.d = 2017.4;
  printf("函數(shù)調(diào)用后,形參data的值,d.i:%d, d.f:%f, d.d:%f\n",data.i,data.f,data.d);
}
 
int main(){
  printf("結(jié)構(gòu)體參數(shù)傳遞示例:\n");
  struct Datedate = {2017,4,2};
  printf("實(shí)參date的地址:%#x\n", &date);
  printf("實(shí)參date的值:%d-%d-%d\n",date.year,date.month,date.day);
  changeStruct(date);
  printf("函數(shù)調(diào)用后,實(shí)參date的值:%d-%d-%d\n",date.year,date.month,date.day);
 
  printf("共用體參數(shù)傳遞示例:\n");
  unionDatadata={.i=2017};
  printf("實(shí)參data的地址:%#x\n", &data);
  printf("實(shí)參data的值,d.i:%d, d.f:%f, d.d:%f\n",data.i,data.f,data.d);
  changeUnion(data);
  printf("函數(shù)調(diào)用后,實(shí)參data的值,d.i:%d, d.f:%f, d.d:%f\n",data.i,data.f,data.d);
 
  return 0;
}
 

編譯后運(yùn)行,輸出如下:

結(jié)構(gòu)體參數(shù)傳遞示例:
實(shí)參date的地址:0x5fcb00
實(shí)參date的值:2017-4-2
形參date的地址:0x5fcae0
形參date的值:2018-12-31
函數(shù)調(diào)用后,實(shí)參date的值:2017-4-2
共用體參數(shù)傳遞示例:
實(shí)參data的地址:0x5fcaf0
實(shí)參data的值,d.i:2017, d.f:0.000000, d.d:0.000000
形參data的地址:0x5fcab0
形參data的值,d.i:2017, d.f:0.000000, d.d:0.000000
函數(shù)調(diào)用后,形參data的值,d.i:-1717986918, d.f:-0.000000, d.d:2017.400000
函數(shù)調(diào)用后,實(shí)參data的值,d.i:2017, d.f:0.000000, d.d:0.000000
 

我們發(fā)現(xiàn),C中的自定義類(lèi)型作為參數(shù)傳遞時(shí),和基本類(lèi)型一樣,也是按值傳遞。

小結(jié)

C語(yǔ)言中,參數(shù)類(lèi)型為字符型、整型、浮點(diǎn)型以及枚舉型、結(jié)構(gòu)體(struct)和共同體(union)時(shí),都是常規(guī)的值傳遞。而指針作為一種特殊的類(lèi)型,其值為一個(gè)地址,所指向的基類(lèi)型可以任意其他類(lèi)型(包括void)甚至可以指向函數(shù),所以,指針作為參數(shù)時(shí)雖然本質(zhì)上屬于值傳遞,但因?yàn)閭鬟f的是一個(gè)地址,可以讓被調(diào)函數(shù)通過(guò)對(duì)指針?biāo)竷?nèi)容的操作直接作用于外部數(shù)據(jù),屬于參數(shù)傳遞中特殊的值傳遞方式。雖然可以把形參聲明為數(shù)組,但實(shí)際的形參卻是指針,因此,數(shù)組作為參數(shù)的傳遞方式也是特殊的值傳遞。

我們通過(guò)依次考察C語(yǔ)言中各種數(shù)據(jù)類(lèi)型發(fā)現(xiàn): C語(yǔ)言中只有值傳遞!

相關(guān)文章

  • C語(yǔ)言string庫(kù)strcpy、strcmp、strcat函數(shù)的使用

    C語(yǔ)言string庫(kù)strcpy、strcmp、strcat函數(shù)的使用

    這篇文章主要介紹了C語(yǔ)言string庫(kù)strcpy、strcmp、strcat函數(shù)的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 詳解C語(yǔ)言初階基礎(chǔ)

    詳解C語(yǔ)言初階基礎(chǔ)

    這篇文章主要介紹了C語(yǔ)言中的初階基礎(chǔ),介紹了其相關(guān)概念,具有一定參考價(jià)值。需要的朋友可以了解下,希望能夠給你帶來(lái)幫助
    2021-11-11
  • C++實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)最新版

    C++實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)最新版

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)最新版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++中的幾個(gè)特殊符號(hào)說(shuō)明

    C++中的幾個(gè)特殊符號(hào)說(shuō)明

    這篇文章主要介紹了C++中的幾個(gè)特殊符號(hào)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C語(yǔ)言在頭文件中定義const變量詳解

    C語(yǔ)言在頭文件中定義const變量詳解

    這篇文章主要介紹了C語(yǔ)言在頭文件中定義const變量詳解的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C++獲取系統(tǒng)時(shí)間的三種方法

    C++獲取系統(tǒng)時(shí)間的三種方法

    在?C++?編程中,獲取系統(tǒng)時(shí)間是一項(xiàng)常見(jiàn)任務(wù),無(wú)論是記錄日志、計(jì)算程序運(yùn)行時(shí)間,還是實(shí)現(xiàn)計(jì)時(shí)功能,都需要獲取當(dāng)前的系統(tǒng)時(shí)間,本文將介紹幾種在?C++?中獲取系統(tǒng)時(shí)間的方法,并提供相應(yīng)的代碼示例,需要的朋友可以參考下
    2024-09-09
  • 淺談C++中thread庫(kù)join和detach的區(qū)別

    淺談C++中thread庫(kù)join和detach的區(qū)別

    這篇文章主要為大家介紹了C++中thread庫(kù)join和detach的區(qū)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-11-11
  • 使用C++實(shí)現(xiàn)Excel文件與CSV之間的相互轉(zhuǎn)換

    使用C++實(shí)現(xiàn)Excel文件與CSV之間的相互轉(zhuǎn)換

    這篇文章主要為大家詳細(xì)介紹了如何使用C++實(shí)現(xiàn)Excel文件與CSV之間的相互轉(zhuǎn)換,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-06-06
  • 簡(jiǎn)單總結(jié)C語(yǔ)言中各種類(lèi)型的指針的概念

    簡(jiǎn)單總結(jié)C語(yǔ)言中各種類(lèi)型的指針的概念

    這篇文章主要簡(jiǎn)單總結(jié)了C語(yǔ)言中各種類(lèi)型的指針的概念,指針可以說(shuō)是C語(yǔ)言本身所具有的最大特性,平時(shí)根據(jù)不同使用場(chǎng)合習(xí)慣地將其簡(jiǎn)單分類(lèi),需要的朋友可以參考下
    2016-03-03
  • 基于C語(yǔ)言實(shí)現(xiàn)的貪吃蛇游戲完整實(shí)例代碼

    基于C語(yǔ)言實(shí)現(xiàn)的貪吃蛇游戲完整實(shí)例代碼

    這篇文章主要介紹了基于C語(yǔ)言實(shí)現(xiàn)的貪吃蛇游戲完整實(shí)例代碼,對(duì)于學(xué)習(xí)游戲開(kāi)發(fā)的朋友有一定的借鑒價(jià)值,需要的朋友可以參考下
    2014-08-08

最新評(píng)論

遂溪县| 新丰县| 广饶县| 屯昌县| 宜阳县| 集贤县| 城口县| 涿州市| 九龙坡区| 朝阳县| 天全县| 伊川县| 永登县| 岗巴县| 蒲江县| 花垣县| 察雅县| 梅州市| 黔西县| 阜康市| 尼玛县| 敖汉旗| 修文县| 施甸县| 定边县| 游戏| 鹤岗市| 静乐县| 密云县| 衡阳县| 南丰县| 星子县| 龙井市| 涞水县| 华坪县| 宁河县| 通江县| 淮滨县| 香港| 鸡西市| 克山县|