名稱空間
變體
操作

生存期

來自 cppreference.com
< c‎ | language

C 語言中,每個物件在程式執行的某個時段記憶體在,擁有一個不變的地址,並保留其最後儲存的值(除非該值為不確定的),對於變長陣列(VLA),還會保留其大小(C99 起)。這個時段被稱為該物件的生命週期

對於宣告為具有自動、靜態和執行緒儲存期的物件,其生命週期等於它們的儲存期(注意非 VLA 和 VLA 自動儲存期之間的區別)。

對於具有已分配儲存期的物件,其生命週期始於分配函式返回時(包括 realloc 的返回),終止於呼叫 realloc 或解除分配函式時。請注意,由於已分配物件沒有宣告型別,因此首次用於訪問該物件的左值表示式的型別會成為其有效型別

在物件的生命週期之外訪問物件是未定義行為。

int* foo(void) {
    int a = 17; // a has automatic storage duration
    return &a;
}  // lifetime of a ends
int main(void) {
    int* p = foo(); // p points to an object past lifetime ("dangling pointer")
    int n = *p; // undefined behavior
}

指向生命週期已結束的物件的指標(或指向物件末尾之外一個位置的指標)具有不確定值。

[編輯] 臨時生命週期

非左值表示式指定的,含有陣列成員的結構體和聯合體物件(無論是直接成員還是巢狀結構體/聯合體成員的成員)具有臨時生命週期。臨時生命週期始於引用此類物件的表示式被求值時,並結束於下一個序列點(C11 前)包含該物件的完整表示式或完整宣告符結束時(C11 起)

任何試圖修改具有臨時生命週期物件的行為都會導致未定義行為。

struct T { double a[4]; };
struct T f(void) { return (struct T){3.15}; }
double g1(double* x) { return *x; }
void g2(double* x) { *x = 1.0; }
int main(void)
{
    double d = g1(f().a); // C99: UB access to a[0] in g1 whose lifetime ended
                          //      at the sequence point at the start of g1
                          // C11: OK, d is 3.15
    g2(f().a); // C99: UB modification of a[0] whose lifetime ended at the sequence point
               // C11: UB attempt to modify a temporary object
}

[編輯] 參考

  • C17 標準 (ISO/IEC 9899:2018)
  • 6.2.4 物件的儲存期 (p: 30)
  • C11 標準 (ISO/IEC 9899:2011)
  • 6.2.4 物件的儲存期 (p: 38-39)
  • C99 標準 (ISO/IEC 9899:1999)
  • 6.2.4 物件的儲存期 (p: 32)
  • C89/C90 標準 (ISO/IEC 9899:1990)
  • 3.1.2.4 物件的儲存期

[編輯] 參閱

C++ 文件 關於 物件生命週期