【整理自用】C++函數傳遞

這個本來是沒什麼需要說明的,但是偏偏是錯了幾道題,發現自己思考不夠嚴謹。

1. 搞清楚到底在說那個變量

函數傳遞,確實存在着值傳遞、址傳遞和引用傳遞三種。但是要搞清楚着通常是對於什麼變量而言的。
以下三個是所謂的值傳遞,值傳遞和引用傳遞最簡單的表達形式:

int abs(int a);
int abs(int *a);
int abs(int &a);

對於形如上述的表達式而言,無論是哪一種形式,a本身都是一個局部變量。都是在調用的時候爲其創造了一個臨時變量,當函數體結束之時,自動銷燬的。
也就是說,哪些僅針對a所做的改變,不論是哪一種傳遞方式,都終將會因爲a的銷燬而灰飛煙滅。對於調用的函數而言不會產生任何的影響。
下面開始仔細說明:

  1. 值傳遞:調用函數只是把變量的值傳遞過來。所以a僅僅只是一個和調用函數實參擁有相同大小的臨時變量。
  2. 址傳遞:調用函數將變量地址傳過來。所以a 一個和調用函數實參擁有相同地址的臨時變量。
  3. 引用傳遞:引用比較特殊。因爲是實參的別名,所以可以簡單認爲是調用實參來臨時旅遊

可能聽上去沒什麼用處,但是其實很重要。比如我們說址傳遞中,當形參改變時,會影響到實參。前提在於:因爲臨時變量與原實參共享地址。因此,我通過臨時變量更改該地址內的數字,即使事後臨時變量消失了,但是原實參地址不變的,所以在同樣的地址內看到的東西,自然是已經生效了。

但是,a畢竟只是一個臨時變量,如果我不通過臨時的東西去和生存週期更長的東西掛鉤,那麼我短暫做過的事情是不會被人看到的。

題目:下面程序輸出的代碼是多少?

void f(char * x)
{
    x++;
    *x='a';
}
int main()
{
    char str [sizeof("hello")];
    strcpy(str, "hello");
    f(str);
    cout<<str;
    return 0;
}

分析:
1. str可以看做是字符串數組的首元素指針。字符串數組分配的空間在地址上是連續的;
2. 生成了一個臨時性的指針變量x,但是它和str指向同一個地址;
3. x++;使得x(內容)地址自增,從而使得它指向字符串數組第二個元素;
4. *x詞句修改了當前x指向地址內部的元素,即字符串數組第二個元素被改變。
5. 此時x變量離開了函數作用域,局部變量被銷燬。

綜上可見,臨時變量x的一生只有一件事是和更長的生長週期掛鉤的,那就是修改了實參字符串數組第二個元素。其他只作用在x自身身上的一切行爲都隨着x自身的消亡而湮滅了,在剩下的函數裏我們是見不到半點痕跡的。
因而,上述輸出str字符串的結果應該是“Hallo”。


題目: 下面程序的輸出結果是:

#include <stdio.h>
#include <stdlib.h>
void fun ( double *pl,double *p2,double *s)
{
    s = ( double*) calloc ( 1,sizeof(double));
    *s = *pl + *(p2+1);
}
main( )
{
    double a [2] = {1.1,2.2},b [2] = {10.0,20.0}, *s = a;
    fun (a,b,s);
    printf ( "%5.2f\n",* s) ;
}

分析:
1. fun(a,b,c)傳入參數,a,b,c分別爲a,b,a數組的首元素的指針。
2. 創建臨時變量p1,p2,s。分別於a,b,a指針擁有同樣的地址。
3. s賦值爲一個指向含有8個字節內容的某一個地址。
4. s地址內放入了p1指向的地址內存放的元素+(p2+1)指向地址存放的內容。注意“指針+1”是加上一個單位量而不是物理地址的1,但是如果是真實的地址量+1,那就是物理地址+1。
5. 此時臨時變量離開了函數作用域,所有局部變量被銷燬。

綜上可見,臨時變量的一生都與更長的生命週期無關,因此對實參不會產生任何影響。
因而答案是:“1.10”

數組名作爲形參,退化爲指針

在C語言中,數組名作爲參數傳給函數時,退化爲指針;需要數組大小時,需要一個參數傳數組名,另一個傳數組大小。
即下面的1,2,3行代碼是等同的。

int fun(char a[]);
int fun(char a[100]);
int fun(char *a);

題目:某32位系統下, C++程序如下所示,sizeof 的值應爲?(22,4 ,4,4)

char str[] = “http://www.renren.com”  (長度爲21)
char *p = str ; 

sizeof (str ) = ?
sizeof ( p ) = ?
void Foo ( char str[100]){
    sizeof( str ) = ?
}
void *p = malloc( 100 );
sizeof ( p ) = ?

所以當利用sizeof的時候返回的將是int指針的內存字節數,只能做這樣的函數了,void fun(int *a,size_t n);才能知道數組大小。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章