Lifetime
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++ 文档
关于
对象生存期
|