gpt4 book ai didi

c - 为什么在我第一次遍历数组时返回本地数组指针有效?

转载 作者:太空宇宙 更新时间:2023-11-04 05:47:28 24 4
gpt4 key购买 nike

我尝试使用返回数组指针来更好地理解它们的工作原理,但发现了一些我无法解释的东西。

为什么每当我在实际返回之前遍历返回数组时,以下代码都有效(请参阅条件部分)?
是不是因为 C 是惰性的,实际上并没有将数组写入内存,因为它认为无论如何都不会访问它?

#include <stdio.h>

//returns pointer to array terminated by (-1)
int* thisDoesntMakeAnySense(int randomNumber) {
int array[randomNumber + 1];

for(int i = 0; i < randomNumber; i++) {
array[i] = i;
}
array[randomNumber] = -1;

#ifdef ENABLE_CLUDGE
int i = 0;
while(array[i] != -1) {
printf("%d\n", array[i]);
i++;
}
#endif
return array;
}

int main() {
int* test = thisDoesntMakeAnySense(3);

while(*test != -1) {
printf("%d\n", *test);
test++;
}
return 0;
}

最佳答案

是的,当您的编译器发现数组在返回之前未被读取时,它会消除写入数组的代码。

这不是懒惰;这是优化。编译器必须做更多的工作来解决这些问题。在编译器中做更多工作的目标是创建一个在执行时做较少工作(或使用较少空间或其他资源)的程序。

这种行为不受 C 标准的保证,但却是编译器的一个共同特征。

请注意,编译器能够忽略您在 main 中尝试的数组读取,因为这些读取未由 C 标准定义。在 thisDoesntMakeAnySense 中,数组 array 在函数开始时创建,并且(在 C 标准使用的计算模型中)在函数返回时销毁。尽管该函数返回一个指向数组的指针,但该数组不存在(在模型中),并且该指针无效。因为指针无效,所以编译器不需要为 main 中使用指针的代码赋予任何意义。因此,C 标准允许编译器推断该程序写入数组但从未从中读取,甚至在 main 中也不读取,因此对数组的写入没有效果,可能是已删除。

一般来说,不需要编译器来生成完全按照编写的源代码执行程序的程序。 C 标准只要求编译器(或通常的 C 实现,包括所有标准头文件和库以及支持软件)生成与源代码具有相同可观察行为的程序。可观察到的行为包括:

  • 写入文件的数据。
  • 输入和输出交互。
  • 访问可变对象。

因此,printf 语句的输出是可观察的行为。但是写入从未使用过的数组是不可观察的行为,因此编译器不需要为其生成代码。

关于碰巧使您的程序看起来正常工作的代码,该代码从数组中读取并写入输出(这是可观察到的行为)。因此程序必须1 写入该输出。您的编译器显然通过实际创建数组、写入数组、然后读取数组并将其写入标准输出来实现这一点。然后,在返回 main 时,由于数组已创建且其在内存中的数据尚未更改,因此 main 中用于打印它的代码恰好“有效”。但是,编译器可以通过使用编译时生成的常量字符串简单地打印输出而不使用数组来实现所需的可观察行为。在这种情况下,main 中的代码将失败。

脚注

1 如果程序没有问题,则程序必须写入输出。然而,程序执行后期存在未定义行为的事实毒化了上游执行。如果程序控制进入存在无条件未定义行为的路径,则整个路径的行为是未定义的。

关于c - 为什么在我第一次遍历数组时返回本地数组指针有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57415474/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com