【发布时间】:2020-10-27 18:24:59
【问题描述】:
有史以来第一个问题:)
我正在“自学”学习编程,正在阅读 K.N.King 的“C Programming: A modern Approach”。在Chapter18 - Declarations 中的 Q&A 部分,有一个问题是关于为什么选择语句和迭代语句(以及它们的“内部”语句)在 C99 中被视为块。在简单介绍了答案后,他说:
[...]C99 标准规定,如果复合文字出现在函数体之外,则由复合文字表示的对象具有静态持续时间。否则有自动保存期限;结果,对象占用的内存在复合文字出现的块的末尾被释放[...]
我想我明白了。我试图从函数返回一个指向复合文字的指针,实际上输出是错误的(或者我猜是未定义的)。我的问题如下;他举了这个例子:
/* 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);
接下来是这样的解释:
每个复合文字都会导致创建一个对象,但该对象仅存在于由包含该文字出现的语句的大括号形成的块中。在调用
evaluate_polynomial时,coefficients指向一个不再存在的对象。结果:未定义的行为。
当我在我的计算机上尝试完全相同的代码时(我在 Linux VM 中使用 GCC),我总是得到正确的输出。一旦“控制流”退出 if 块,文字似乎不会被释放。
有人可以详细说明一下吗?
谢谢。
【问题讨论】:
-
嗯,这就是“未定义行为”的意思。它可能看起来有效,但并没有真正定义为这样做。您正在访问一些不再分配给对象的内存,但可能会意外包含一些产生“预期”结果的数据。
-
字面量为
{1.5, -3.0, 6.0}字面量必须存在于程序某处,否则无法赋值。所以在退出块时,coefficients指向文字。 -
编译器当然可以创建一个新对象,将文字复制到该对象,在赋值中使用其地址,然后在退出块时释放内存,这将导致未定义的行为。
-
您的编译器似乎使用了我的第一个解释。另一个编译器可以使用第二种解释。
-
真的只是Can a local variable's memory be accessed outside its scope?的另一个骗子;标记为
c++,但与 C 没有任何相关变化
标签: c scope storage c99 compound-literals