1. 程式人生 > >徹底高清值傳遞與地址傳遞的區別

徹底高清值傳遞與地址傳遞的區別

1. 考題一:程式程式碼如下:
void Exchg1(int x, int y) 
{
  int tmp;
  tmp=x;
  x=y;
  y=tmp;
  printf(“x=%d,y=%d/n”,x,y)
}
void main()
{
  int a=4,b=6;
  Exchg1 (a,b) ;
  printf(“a=%d,b=%d/n”,a,b)
}
輸出的結果:
x=____, y=____
a=____, b=____
問下劃線的部分應是什麼,請完成。

2. 考題二:程式碼如下。
Exchg2(int *px, int *py)
{
  int tmp=*px;
  *px=*py;
   *py=tmp;
  print(“*px=%d,*py=%d/n”,*px,*py);
}
main()
{
  int a=4;
  int b=6;
      Exchg2(&a,&b);
      Print(“a=%d,b=%d/n”, a, b);
}
輸出的結果為:
*px=____, *py=____
a=____, b=____
問下劃線的部分應是什麼,請完成。

3. 考題三:
Exchg2(int &x, int &y)
{
   int tmp=x;
   x=y;
   y=tmp;
  print(“x=%d,y=%d/n”,x,y);
}
main()
{
  int a=4;
  int b=6;
      Exchg2(a,b);
      Print(“a=%d,b=%d/n”, a, b);
}
輸出的結果:
x=____, y=____
a=____, b=____
    問下劃線的部分輸出的應是什麼,請完成。

    你不在機子上試,能作出來嗎?你對你寫出的答案有多大的把握?
    正確的答案,想知道嗎?(呵呵,讓我慢慢地告訴你吧!)
    好,廢話少說,繼續我們的探索之旅了。
   我們都知道:C語言中函式引數的傳遞有:值傳遞,地址傳遞,引用傳遞這三種形式。題一為值傳遞,題二為地址傳遞,題三為引用傳遞。不過,正是這幾種引數傳遞的形式,曾把我給搞得暈頭轉向。我相信也有很多人與我有同感吧?
下面請讓我逐個地談談這三種傳遞形式。

二. 函式引數傳遞方式之一:值傳遞

1. 值傳遞的一個錯誤認識
    先看題一中Exchg1函式的定義:
void Exchg1(int x, int y)   //定義中的x,y變數被稱為Exchg1函式的形式引數
{
  int tmp;
  tmp=x;
  x=y;
  y=tmp;
  printf(“x=%d,y=%d/n”,x,y)
}
問:你認為這個函式是在做什麼呀?
答:好像是對引數x,y的值對調吧?
    請往下看,我想利用這個函式來完成對a,b兩個變數值的對調,程式如下:
void main()
{
  int a=4,b=6;
  Exchg1 (a,b)     //a,b變數為Exchg1函式的實際引數。
/  printf(“a=%d,b=%d/n”,a,b)
}
    我問:Exchg1 ()裡頭的  printf(“x=%d,y=%d/n”,x,y)語句會輸出什麼啊?
    我再問:Exchg1 ()後的  printf(“a=%d,b=%d/n”,a,b)語句輸出的是什麼?
    程式輸出的結果是:
x=6 , y=4 
a=4 , b=6  //為什麼不是a=6,b=4呢?

    奇怪,明明我把a,b分別代入了x,y中,並在函式裡完成了兩個變數值的交換,為什麼a,b變數值還是沒有交換(仍然是a==4,b==6,而不是a==6,b==4)?如果你也會有這個疑問,那是因為你跟本就不知實參a,b與形參x,y的關係了。

2. 一個預備的常識
為了說明這個問題,我先給出一個程式碼:
int a=4;
int x;
x=a;
x=x+3;
    看好了沒,現在我問你:最終a值是多少,x值是多少?
    (怎麼搞的,給我這個小兒科的問題。還不簡單,不就是a==4  x==7嘛!)
    在這個程式碼中,你要明白一個東西:雖然a值賦給了x,但是a變數並不是x變數哦。我們對x任何的修改,都不會改變a變數。呵呵!雖然簡單,並且一看就理所當然,不過可是一個很重要的認識喔。

3. 理解值傳遞的形式
看呼叫Exch1函式的程式碼:

main()
{
  int a=4,b=6;
  Exchg1(a,b) //這裡呼叫了Exchg1函式       
  printf(“a=%d,b=%d”,a,b)
}

Exchg1(a,b)時所完成的操作程式碼如下所示。
int x=a;//←
int y=b;//←注意這裡,頭兩行是呼叫函式時的隱含操作
int tmp;
tmp=x;
x=y;
y=tmp;
    請注意在呼叫執行Exchg1函式的操作中我人為地加上了頭兩句:
int x=a;
int y=b;
    這是呼叫函式時的兩個隱含動作。它確實存在,現在我只不過把它顯式地寫了出來而已。問題一下就清晰起來啦。(看到這裡,現在你認為函式裡面交換操作的是a,b變數或者只是x,y變數呢?)
    原來 ,其實函式在呼叫時是隱含地把實參a,b 的值分別賦值給了x,y,之後在你寫的Exchg1函式體內再也沒有對a,b進行任何的操作了。交換的只是x,y變數。並不是a,b。當然a,b的值沒有改變啦!函式只是把a,b的值通過賦值傳遞給了x,y,函式裡頭操作的只是x,y的值並不是a,b的值。這就是所謂的引數的值傳遞了。
    哈哈,終於明白了,正是因為它隱含了那兩個的賦值操作,才讓我們產生了前述的迷惑(以為a,b已經代替了x,y,對x,y的操作就是對a,b的操作了,這是一個錯誤的觀點啊!)。

三. 函式引數傳遞方式之二:地址傳遞
繼續——地址傳遞的問題!
看題二的程式碼:
Exchg2(int *px, int *py)
{
  int tmp=*px;
  *px=*py;
  *py=tmp;
  print(“*px=%d,*py=%d/n”,*px,*py);
}
main()
{
  int a=4;
  int b=6;
      Exchg2(&a,&b);
      Print(“a=%d,b=%d/n”, a, b);
}
它的輸出結果是:
  *px=6,*py=4
  a=6,b=4

    看函式的介面部分:Exchg2(int *px,int *py),請注意:引數px,py都是指標。
    再看呼叫處:Exchg2(&a, &b);
    它將a的地址(&a)代入到px,b的地址(&b)代入到py。同上面的值傳遞一樣,函式呼叫時作了兩個隱含的操作:將&a,&b的值賦值給了px,py。
px=&a;
py=&b;
    呵呵!我們發現,其實它與值傳遞並沒有什麼不同,只不過這裡是將a,b的地址值傳遞給了px,py,而不是傳遞的a,b的內容,而(請好好地在比較比較啦)
    整個Exchg2函式呼叫是如下執行的:
  px=&a;   //
  py=&b;   //請注意這兩行,它是呼叫Exchg2的隱含動作。
  int tmp=*px;
  *px=*py;
  *py=tmp;
  print(“*px=%d,*py=%d/n”,*px,*py);
    這樣,有了頭兩行的隱含賦值操作。我們現在已經可以看出,指標px,py的值已經分別是a,b變數的地址值了。接下來,對*px,*py的操作當然也就是對a,b變數本身的操作了。所以函式裡頭的交換就是對a,b值的交換了,這就是所謂的地址傳遞(傳遞a,b的地址給了px,py),你現在明白了嗎?

四. 函式引數傳遞方式之三:引用傳遞
    看題三的程式碼:
Exchg3(int &x, int &y) //注意定義處的形式引數的格式與值傳遞不同
{
   int tmp=x;
   x=y;
   y=tmp;
  print(“x=%d,y=%d/n”,x,y);
}
main()
{
  int a=4;
  int b=6;
      Exchg3(a,b);  //注意:這裡呼叫方式與值傳遞一樣
      Print(“a=%d,b=%d/n”, a, b);
}
輸出結果:
x=6, y=4
a=6, b=4   //這個輸出結果與值傳遞不同。
    看到沒有,與值傳遞相比,程式碼格式上只有一處是不同的,即在定義處:
Exchg3(int &x, int &y)。
    但是我們發現a與b的值發生了對調。這說明了Exchg3(a,b)裡頭修改的是a,b變數,而不只是修改x,y了。
    我們先看Exchg3函式的定義處Exchg3(int &x,int &y)。引數x,y是int的變數,呼叫時我們可以像值傳遞(如: Exchg1(a,b); )一樣呼叫函式(如: Exchg3(a,b); )。但是x,y前都有一個取地址符號&。有了這個,呼叫Exchg3時函式會將a,b 分別代替了x,y了,我們稱x,y分別引用了a,b變數。這樣函式裡頭操作的其實就是實參a,b本身了,也就是說函式裡是可以直接修改到a,b的值了。

   最後對值傳遞與引用傳遞作一個比較:

1. 在函式定義格式上有不同:
值傳遞在定義處是:Exchg1(int x, int y);
引用傳遞在這義處是:Exchg1(int &x, int &y);

2. 呼叫時有相同的格式:
值傳遞:Exchg1(a,b);
引用傳遞:Exchg3(a,b);

3. 功能上是不同的:
值傳遞的函式裡操作的不是a,b變數本身,只是將a,b值賦給了x,y函式裡操作的只是x,y變數而不是a,b,顯示a,b的值不會被Exchg1函式所修改。
引用傳遞Exchg3(a,b)函式裡是用a,b分別代替了x,y。函式裡操作的是a,b

相關推薦

徹底傳遞地址傳遞區別

1. 考題一:程式程式碼如下:void Exchg1(int x, int y)  {  int tmp;  tmp=x;  x=y;  y=tmp;  printf(“x=%d,y=%d/n”,x,y)}void main(){  int a=4,b=6;  Exchg1

## 標題:指標的傳遞地址傳遞,全域性變數傳遞形參傳遞區別結果

標題:指標的值傳遞與地址傳遞,全域性變數傳遞,與形參傳遞的區別與結果 1.值傳遞與地址傳遞 下面看著段程式碼:void swap(int a, int b){ int t; t=a; a=b; b=t; } void swap1(int *p1,int *p2){ int t; t=*p

傳遞地址傳遞

作為開發人員,入門級的理解,就是值傳遞和地址傳遞的區別,這是C語言中的基礎。今天通過一個oc的demo理解一下面向物件中的值傳遞和地址傳遞,首先定義一個自定義類MyFunction,定義值傳遞和地址傳遞的方法 -(int)byValue:(int)x { x++; return x

C語言引數傳遞----傳遞地址傳遞

最近開始復(yu)習(xi)C語言,看到引數傳遞這裡,又遇到了以前一直沒有搞清楚的一個問題,我相信這個問題大家許多初學者也會遇到過,就是C語言函式的引數傳遞方式。 C語言中引數的傳遞有兩種方式: 1)值傳遞 2)地址傳遞 3)陣列作為函式引數 這裡用兩

物件作為引數的傳遞地址傳遞

1.沒有明確宣告為指標或者引用,都是值傳遞,會呼叫物件過載的=,建立新的物件。2.當指定為指標型別的時候為傳遞的是指標(地址),指定引數型別為引用的時候,傳遞的也是地址。#include<stdi

java 傳遞地址傳遞(引用)的區別

JAVA傳遞引數有兩種方式:值傳遞和引用傳遞 值傳遞是傳遞資料:如基本資料型別都是值傳遞 引用傳遞是把形參和實參的指標指向了堆中的同一物件,物件的引用和陣列的引用。 注意: 實參,J

函式的傳遞地址傳遞--以輸入三個數並從小到大排列為例

一、值傳遞 #include <stdio.h> //自定義函式實現三個數從小到大排列 //值傳遞 //編者:wsg void sort(int a, int b, int c) { int t; if(a>b) { t = a;

函式引數函式呼叫(徹底理解傳遞引用傳遞)

函式呼叫的作用: ·用實引數向形式引數傳遞資料; ·為獲得資料引數及在函式體中宣告的變數分配儲存空間; ·中斷現行(呼叫)函式,把流程向被呼叫函式的入口處,開始執行被調函式。當引數表為空時,表示該函式不從呼叫函式接受資料。 函式引數傳遞機制   堆疊儲存區是主調函式(過程)

Java——傳遞引用傳遞

color 16px code mar 變量 參數傳遞 形參 函數 ava 1.基本類型和引用類型在內存中的保存 (1)基本類型的變量保存原始值,即它代表的值就是數值本身;    基本類型在聲明變量時就為它分配了空間;    基本類型在參數傳遞過程中屬於值傳遞,也就是復

傳遞引用傳遞

double 字符 浮點型 ima 原來 例子 布爾 println private 基本數據類型 (屬於值傳遞) 整型:byte,short,int,long 浮點型:float,double 字符型:char 布爾型:boolean 引用數據

面試再問傳遞引用傳遞,把這篇文章砸給他!

java的值傳遞和引用傳遞在面試中一般都會都被涉及到,今天我們就來聊聊這個問題,首先我們必須認識到這個問題一般是相對函式而言的,也就是java中的方法引數,那麼我們先來回顧一下在程式設計語言中有關引數傳遞給方法(或函式)的兩個專業術語: 按值呼叫(call by value)

ethereum(以太坊)(四)--傳遞引用傳遞

pragma solidity ^0.4.0; // priveta public internal contract Test{ uint public _age; function Test(uint age){ _age = age; }

javascript傳遞引用傳遞

javascript中,變數型別分為基本型別和物件型別,基本型別有以下幾種:string,number,boolean,null,undefined,物件型別就是object,object又分為object,array,function。基本型別是值傳遞,物件型別是引用傳遞。具體來說,就是基本型

java的引數傳遞傳遞還是地址傳遞

java的引數傳遞是值傳遞還是地址傳遞結論: 1、基本型別作為引數傳遞時,是傳遞值的拷貝,無論你怎麼改變這個拷貝,原值是不會改變的 2、物件作為引數傳遞時,是把物件在記憶體中的地址拷貝了一份傳給了引數。 基本型別作為引數傳遞 public class Test1

JAVA引數傳遞方式 (按傳遞引用傳遞區別)

首先要明確的是JAVA中沒有引用傳遞, 全部是按值呼叫 令大家所費解的 當物件引用作為引數時  函式為什麼能修改真實的物件呢?這不是引用傳遞的特徵嗎? 尤其先學習C++再學習JAVA的同學(比如說我自己)會這樣認為, 用白話解釋就是: 引用傳遞指標時, 連函式操作的指

C# 二十四、傳遞引用傳遞

值傳遞 使用值傳遞時,向形式引數傳遞的是實在引數的副本,方法內發生的對形式引數的更改對實在引數本身沒有任何影響。 程式碼示例: static void Main(string[] args) { int i =

javascript中傳遞地址傳遞,引用傳遞的問題。

首先發現問題是好事情,只有發現問題,才會有提高,不然整體都在寫相同的程式碼,寫個幾年,不還是原來的水平。 這個地址傳遞和值傳遞 不論在什麼語言都有這個問題,一旦出問題,就是很微妙的問題。想破天都不知道為啥的時候,多半就是 這個問題在作怪啦。 (js,java,c)c語言的

C#中傳遞引用傳遞區別

以值傳遞引數 當實參當作值來傳遞時,就產生了一個新的拷貝。 class Test { static void Main(string[] args) { int x=8; Fo(x);

java基礎–(11)–關於Java中的傳遞“引用傳遞

結論:Java中都是值傳遞,沒有“引用傳遞” (1)基本資料型別傳值,對形參的修改不會影響實參; (2)引用型別傳引用的值,形參和實參指向同一個記憶體地址(同一個物件),所以對引數的修改會影響到實際的物件; (3)String, Integer, Double等immutable的型別特殊處

Java中傳遞引用傳遞

//Test.java public class Test { public static void main(String[] args) { Person ps =