2013-07-27 68 views
4

我讀函數調用之間的return
並用下面的代碼片段嘗試:什麼是函數返回值的生命週期?

/* file structaddr.c */ 
#include <stdio.h>  
#define MSIZE 10 

struct simple 
{ 
    char c_str[MSIZE]; 
}; 
struct simple xprint(void) 
{ 
    struct simple ret = { "Morning !" }; 
    return ret; 
} 
int main(void) 
{ 
    printf("Good %s\n", xprint().c_str);  
    return 0; 
} 

的代碼是沒有錯誤和警告編譯。
使用測試GCC 4.4.3(Ubuntu 4.4.3-4ubuntu5.1)Visual C++編譯器。

gcc -m32 -std=c99 -Wall -o test structaddr.c 
cl -W3 -Zi -GS -TC -Fetest structaddr.c 

輸出:
早安!

我對結果有點困惑。
該代碼是否正確寫入?

我的問題:

  • 功能return值的可見性是什麼(陣列從上面的例子中一 struct),以及如何正確地訪問它們?

  • 哪裏結束return價值的壽命?

+0

返回值是一個臨時值。它在使用後被丟棄。如果你沒有把它存儲到一個變量中,那麼在你第一次引用它之後它就消失了。 – 2013-07-27 20:20:08

+0

@JoachimPileborg是的,我剛剛在你的評論之前刪除了我的評論。 :) –

+0

@boleto你爲什麼困惑?你期望別的嗎? – Xaqq

回答

5

在C中,臨時的在您的示例的壽命結束時的printf表達式完成:

  • 的每個C 2011(N1570)6.2.4 8,臨時的壽命結束時的評價包含它的完整表達式(或聲明符)結束:「結構或聯合類型的非左值表達式,其中結構或聯合包含具有數組類型的成員(包括遞歸地包含所有包含的結構和聯合的成員)指的是具有自動存儲持續時間和臨時生命週期的對象.36)它的生存期在評估表達式並且其初始值爲表達式的值時開始。當包含完整表達式或完整聲明符的評估結束時,它的生命期結束。「
  • 根據6.8 4:」完整表達式是不是另一個表達式或聲明符的一部分的表達式「。根據6.7.6 3: 「完整的聲明符是不屬於另一個聲明符的聲明符。」
  • 因此,當printf表達式完成時,示例中臨時對象的生存期結束。

在C++中,在您的示例的壽命一樣C:

  • 每C++ 2010(N3092)12.2 3:「臨時對象被銷燬如在評價全最後一步表達式(1.9)表示(詞彙)包含它們被創建的點。「
  • 每12。2 4和5:「有兩種情況下臨時銷燬在不同於完整表達式末尾的點。第一個上下文是當調用默認構造函數來初始化數組的元素時。如果構造函數有一個或多個默認參數,則在構造下一個數組元素(如果有)之前,對在默認參數表達式中創建的每個臨時對象的銷燬都進行排序。「」第二個上下文是當引用綁定到臨時對象時。引用所綁定到的臨時對象或引用所綁定到的子對象的完整對象的臨時對象在引用的生命週期內一直存在,除了:...「(爲簡潔起見,我省略了例外,因爲它們不適用)
  • 因此,您的示例在C++中是相同的,臨時對象作爲評估printf表達式的最後一步被銷燬。
+0

我一直看到的方式是返回的對象將不會超過下一個序列點,這是由調用printf造成的。函數調用之前沒有對錶達式進行評估嗎? – Sebivor

+0

@EricPostpischil,很好的解釋!只是一個小問題 - 調用'printf()'函數時可以修改* array data *嗎? – boleto

+0

@boleto如果您詢問是否將導致相應參數指向的對象寫入的printf格式說明符存在,那麼存在。但是,函數的返回值不是可修改的左值,因此任何嘗試寫入它的操作都是未定義的行爲。 – Sebivor

2

xprint返回結構的副本的功能,並且編譯器存儲該拷貝在一個暫時的,臨時對象壽命是printf函數呼叫的持續時間。當printf函數返回時,該臨時對象被銷燬。

+0

不,但是這段代碼會給出分段錯誤.. –

相關問題