例如:

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结束.

C++相关问答推荐

segfault在C中使用getline()函数

与unions 的未定义行为

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

exit(EXIT_FAILURE):Tcl C API类似功能

如何在Visual Studio代码中关闭此函数名称显示功能?

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

无效指针值在函数调用之间莫名其妙地改变

如何使解释器存储变量

每次除以或乘以整数都会得到0.0000

这个C程序在工作中途停止获取输入.我收到分段故障(核心转储).我还是不知道问题出在哪里

tick.q中的Kdb+键控表语法

在进程之间重定向输出和输入流的问题

可变宏不能编译

我在C程序的Flex/Bison中遇到语法错误

即使我在C++中空闲,也肯定会丢失内存

C中的char**v*char[]

强制GCC始终加载常量(即只读),即使启用了优化

当读取可能会阻塞管道中的父进程时,为什么要等待子进程?

C 中从 Unix 纪元时间转换的损坏

窗口消息处理函数以某种方式更改了应保持不变的 int 变量的值