Namespaces
Variants

Lifetime

From cppreference.net

C语言中的每个 对象 都客观存在,拥有固定地址,在程序执行的某个时间段(称为该对象的 生存期 )内会保持最后存储的值(除非该值不确定) ,对于VLA还会保持其尺寸 (C99起)

对于具有自动、静态和线程存储期的对象,其生存期等于它们的 存储期 (注意非VLA和VLA自动存储期之间的区别)。

对于具有已分配存储期的对象,其生存期始于分配函数返回时(包括从 realloc 返回),止于 realloc 或解分配函数被调用时。需注意由于已分配对象没有 声明类型 ,首次用于访问该对象的左值表达式的类型即成为其 有效类型

在对象生命周期之外访问它是未定义行为。

int* foo(void) {
    int a = 17; // a具有自动存储期
    return &a;
}  // a的生命周期结束
int main(void) {
    int* p = foo(); // p指向已结束生命周期的对象("悬垂指针")
    int n = *p; // 未定义行为
}

指向生命周期已结束的对象(或对象末尾之后位置)的指针具有不确定的值。

临时对象生存期

具有数组成员(直接成员或嵌套结构体/联合体成员的成员)的结构体和联合体对象,若由 非左值表达式 指代,则具有 临时生命周期 。临时生命周期始于指代该对象的表达式求值时,结束于 下一个 序列点 (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:未定义行为,在g1开始时序列点处a[0]的生命周期已结束
                          // C11:合法,d的值为3.15
    g2(f().a); // C99:未定义行为,在序列点处a[0]的生命周期已结束
               // C11:未定义行为,尝试修改临时对象
}

参考文献

  • 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 对象的存储期(页码:32)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 3.1.2.4 对象的存储期

参见

C++ 文档 关于 对象生存期