C 中的复合文字存储持续时间

Compund literals storage duration in C

第一个问题:)

我正在“自学”编程,正在阅读 “C 编程:现代方法” K.N.King。在Chapter18 - Declarations中,在问答部分,有一个问题是关于为什么选择语句和迭代语句(及其“内部”语句)在 C99 中被认为是块。在对答案进行了简短介绍后,他说:

[...]The C99 standard states that the object represented by a compund literal has static duration if the compound literal occurs outside the body of a function. Otherwise, it has automatic storage duration; as a result, the memory occupied by the object is deallocated at the end of the block in which the compound literal appears[...]

我想我明白了。我已经尝试 return 一个指向函数复合文字的指针,但实际上输出是错误的(或者我猜是未定义的)。我的问题如下;他给出了这个例子:

/* Example 2 - if statements with braces */

double *coefficients, value;

if(x){
    coefficients = (double[3]) {1.5, -3.0, 6.0};
}else{
    coefficients = (double[3]) {4.5, 1.0, -3.5};
}
value = evaluate_polynomial(coefficients);

后面是这个解释:

Each compound literal causes an object to be created, but that object exists only within the block formed by the braces that enclose the statement in which the literal appears. By the time evaluate_polynomial is called, coefficients points to an object that no longer exist. The result: undefined behavior.

当我在我的计算机中尝试完全相同的代码时(我在 Linux VM 中使用 GCC),我总是得到正确的输出。一旦“控制流”退出 if 块,文字似乎就不会被释放。

有人可以详细说明一下吗?

谢谢。

出于性能原因,当程序到达变量作用域的末尾时(或者这个变量是freed),它的内容不会被删除。但是它的内存地址 以后可能会 被重新用于存储另一个导致 Undefined Behavior.

的变量

因此,如果您稍后在程序中打印系数,它们 可能 或可能不符合您的预期值。

如果您想说明这一点,您可以在变量的退出块和读取变量的指令之间逐步添加越来越多的代码。在某些时候,您的变量 可能 没有预期值。

请小心避免未定义的行为,因为它们会导致难以重现错误(例如,程序在 99% 的时间都可以正常工作,但只有 1% 的时间会崩溃)。

尽管 C99 标准将复合文字视为可以获取其地址的左值,但标准对它们的生命周期规则意味着代码应避免获取复合文字的地址,除非地址将立即传递给函数不会保留它的副本,也不会获取内容永远不会改变的大型自动持续时间复合文字的地址。代码不应执行这些操作,而应声明一个具有适当类型和值的常规命名对象(静态常量,如果该值永远不会更改),并传递该对象的地址。

将复合文字的生命周期限制在块范围而不是函数范围的规定理由是,如果重新执行定义复合文字的代码,则不必为复合文字的新实例分配 space .考虑到允许复合文字之前的代码转到与复合文字位于同一块但位于其之前的标签,但是,有必要考虑在由一个创建的对象的生命周期内执行复合文字的可能性较早执行相同的文字可能不会创建单独分配的对象;一旦针对“goto”场景处理了该问题,这也将避免如果复合文字的生命周期受封闭函数限制而出现的任何类似问题。