临时生存期
对象的生存期(lifetime)是程序执行过程中保证为其保留存储空间的时间段。对象在整个生存期内地址保持不变,并保留最后存储的值。如果对象在其生存期外被引用,该行为是未定义的。
注:“地址不变”是指一次执行中不同时间构造的指向相同对象的两个指针比较结果相等;但在同一程序的两次不同执行中,地址可能不同。
包含由非左值表达式(non-lvalue expression)指定的数组成员(直接成员或者嵌套结构/联合成员的成员)的结构和联合具有临时生存期(temporary lifetime)。
#define LENGTH 2 /*自定义包含数组类型成员的结构。*/ typedef struct {int arr[LENGTH];} Temp; /*返回包含数组类型成员的结构的函数。*/ Temp func(int x, int y) { return (Temp){x, y}; }
函数调用表达式是非左值表达式,上述函数返回类型是包含数组类型成员的结构类型,所以这里函数调用表达式func()具有临时生存期。
访问此类数组成员时,会隐式地获取此类对象的地址,例如:
printf("%d\n", *func(2,5).arr); //第一个数组元素的值。 printf("%d\n", *(func(2,5).arr + 1)); //第二个数组元素的值。 printf("%p\n", func(2,5).arr); //第一个数组元素的地址。 printf("%p\n", func(2,5).arr + 1); //第二个数组元素的地址。
这里调用了四次func函数,尽管参数相同,但四个函数调用表达式func(2, 5)却是不同的对象,例如下述表达式结果为真。
func(2,5).arr != func(2,5).arr
具有临时生存期对象的生存期从表达式评估开始到包含该表达式的完整表达式评估结束。根据ISO/IEC 9899:2018第6.2.4 Storage durations of objects节,试图修改具有临时生存期的对象将导致未定义行为。
主要参考资料: