例如:
struct A { char s[10]; } f() {
struct A ret;
scanf("%9s", ret.s);
return ret;
}
int main()
{
char *str = f().s;
puts(str);
}
str
是否指向有效的字符串?或者它已经被释放了?
如果它是安全的,那么字符串数据存储在哪里?Main的堆栈框架?
例如:
struct A { char s[10]; } f() {
struct A ret;
scanf("%9s", ret.s);
return ret;
}
int main()
{
char *str = f().s;
puts(str);
}
str
是否指向有效的字符串?或者它已经被释放了?
如果它是安全的,那么字符串数据存储在哪里?Main的堆栈框架?
str
是否指向有效的字符串?或者它已经被释放了?
不是的.在执行对free
或类似 routine 的调用的意义上,它还没有被释放,但是在判断初始化器f().s
之后,它的生命周期 结束.
这是一种罕见的temporary lifetime的物体.该函数返回的值不是左值,无论该函数是像在原始代码中那样使用复合文字实现的,还是像在当前代码中那样使用自动对象实现的.在任何一种情况下,该函数都返回具有 struct 类型的值;它不返回具有普通生存期之一的普通对象.
C 2018 6.2.4 8专门针对这种情况,使用包含数组的 struct 类型的非左值表达式:
具有 struct 或联合类型的非左值表达式,其中 struct 或联合包含数组类型的成员(递归地包括所有包含的 struct 和联合的成员)引用具有自动存储持续时间和temporary lifetime的对象.它的生存期从计算表达式时开始,其初始值是表达式的值.当包含完整表达式的求值结束…时,其生存期结束
在char *str = f().s;
中,f().s
是一个完整的表达式(不包含在任何其他表达式中的表达式).因此,当这个完整表达式的求值完成时,对象的生存期结束,用于它的内存不再保留在C模型中.因此,当执行puts(str);
时,C标准并不保证str
指向包含函数产生的数据的内存,或者它根本不是有效的指针.
如果代码是puts(f().s);
,那就没问题了,因为f().s
将在一个更大的表达式中,它的生命周期将一直持续到puts
结束.