藍森林首頁 | 返回主頁 | 本站地圖 | 站內搜索 | 聯繫信箱 |
 您目前的位置:首頁 > 自由軟件 > 技術交流 > 應用編程


    

藍森林 http://www.lslnet.com 2006年6月6日 10:18


函數調用時的參數傳遞研究

大家都知道,c函數調用時有兩種方法:值傳遞和址傳遞:
值傳遞,如:
void swap(int a, int b)

{
    int temp;
    temp=a;
    a=b;
    b=temp;
}

void Test(void)
{
    int m(5),n(9);
    swap(m,n);
}
函數的執行結果大家一定都很清楚,調用函數test中的m,n沒有發生變化,而被調用函數swap中的局部變量a,b被交換.
址傳遞,如:
void swap(int *a, int* b)

{
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;
}

void Test(void)
{
    int m(5),n(9);
    swap(&m,&n);
}
完成類似的功能,但是無論是調用函數還是被調用函數中的變量內容都被交換.
看上去很簡單,是吧,那麼下面這個例子是值傳遞還是址傳遞呢?
void GetMemory(char *p, int num)

{

    p = (char *)malloc(sizeof(char) * num);

}

void Test(void)

{

    char *str = NULL;

    GetMemory(str, 100);    // str 仍然為 NULL  

    strcpy(str, "hello");   // 運行錯誤

}
答案是值傳遞,大家一定會問了,明明傳遞的是指針,為什麼是值傳遞呢, 其實在編譯器中到底是值傳遞還是址傳遞並不是看傳遞的是不是指針,而是看調用函數中(test)的實際參數是變量本身還是變量的地址,這個變量可以是int,float,char,也可以是指針int*,float*,char*,在這個例子中,傳遞的是指針變量char* str,所以是值傳遞,弄清楚了值傳遞還是址傳遞有什麼意義呢,準確的區分兩者的區別對於我們實現高質量的編程很重要.值傳遞時,編譯器簡單地為實際參數做一個備份,完成被調用函數地功能;址傳遞在兩種情況下使用:
1.需要將一個較大地對像或者實例作為參數傳給被調用函數的情況
2.當參數值必須被修改後返回的情況
第一種情況實際就是我們上面的例子,嚴格的來說,它是值傳遞,我把它叫做偽址傳遞,對於第二種情況,大家肯定都遇到過這種使用方法,如下面的例子:
void GetMemory2(char **p, int num)

{

    *p = (char *)malloc(sizeof(char) * num);

}

void Test2(void)

{

    char *str = NULL;

    GetMemory2(&str, 100);  // 注意參數是 &str,而不是str

    strcpy(str, "hello");   

    cout<< str << endl;

    free(str);  

}
在這個例子中str在被調用函數中動態分配了內存,在調用函數test中使用了在GetMemory2中被修改的參數,大家在實際情況中會遇到很多類似的使用.很遺憾,對於值傳遞,址傳遞一般的c教程中都未能對以上這種差別作出區分,而這些差別又會給初學者很大的誤導,希望大家小心區分:)


函數調用時的參數傳遞研究

**p 可以認為是*p的地址傳遞吧

剛開始時我也不知道要什麼返回指針 後來試過多次後才知道應該使用二級指針的形式 當然如果要返回二級指針的值那麼應該使用三級指針了

以此類推

這個對C語言開發的比較有用 就轉到C版吧     讓更多的人分享你的知識

函數調用時的參數傳遞研究

-->     

怎麼分清楚對於char * a而言:
func(a)是傳遞的a本身還是a的地址?   

對於上面那個例子,如果改成:

[code] void swap(int *a, int* b)

{
int temp;
temp=*a;
*a=*b;
*b=temp;
}

void Test(void)
{
int *m,*n;
m=(int *) malloc(1);
n=(int *)malloc(1);
*m=5;*n=9;
swap(m,n);
free(m);
free(n);
} [/code]

m和n不還是地址傳遞嗎?
swap並沒有定義成二級指針啊?
原來一直認為指針一定是地址傳送,現在知道不對,但怎麼理解呢?那位能詳細解釋一下.

函數調用時的參數傳遞研究

呵呵,指針的值是一個地址,所以你說地址傳遞是指的指針的內容,其實就是指針變量的值。
關於指針的理解我在一個帖子裡仔細論述過,被無雙刪了。

函數調用時的參數傳遞研究

謝謝樓上的回答,偶有些明白了,偶上面說的那個是值傳送,只不過這個值是個地址而以。

函數調用時的參數傳遞研究

樓主的分析有一定的參考價值。
fieryfox 所說的理解是什麼?

函數調用時的參數傳遞研究

是啊,把你那個理解貼出來看看。

函數調用時的參數傳遞研究

感謝大家的捧場,看來大家都注意導這個問題了,對於li2002的問題,char * a,定義了a是一個char*的指針,而函數func(a)直接調用了該變量(在這裡,這個變量是一個指針),所以應該叫做值傳遞,不具備返回參數的功能.
對於我上面的問題,有一點補充,一般情況下,對於一個函數而言,如果需要返回參數的時候,推薦使用返回值來表示函數的執行結果,對於返回的參數,則使用我上面說的址傳遞的第二種情況,當然這也不是絕對的,只是一個大的原則,參見thinking in c++,例子可以參考我的第3 個示例,謝謝大家!:)

函數調用時的參數傳遞研究

#include <stdio.h>;

struct A {
        char *a;
};

int getmemory(struct A *a, int num)
{
        a->;a=(char *) malloc(num);
        return 0;
}

main() {
        struct A a;
        getmemory(&a, 100);
        strcpy(a.a, "hello");
        printf("%s", a.a);
        free(a);
}
:P

函數調用時的參數傳遞研究

是呀,歷歷1979的例子和我下面的這個例子不是一樣嗎.
void CAboutDlg::GetMemory(char* p,int len)
{
        p=(char*)malloc(sizeof(char)*len);
}
void CAboutDlg::OnOK()
{
        char  str=0;
        GetMemory(&str,100);
        memcpy(&str,"hello",6);
        free(&str);
        str=NULL;
        CDialog::OnOK();
}



Copyright © 1999-2000 LSLNET.COM. All rights reserved. 藍森林網站 版權所有。 E-mail : webmaster@lslnet.com