警告:函数返回局部变量的地址

7
我正在用C语言编写一个计算函数,并希望将其作为数组值返回给另一个函数,方法如下。
455                         calculated_val = calculation(value_perf);


358 int calculation(double* dataset){
359
360         double calculated[8] = {};
361         calculated[0] = dataset[7]/dataset[5];
362         calculated[1] = (dataset[0] + dataset[1] + dataset[2] - dataset[3] - dataset[4])/(dataset[5]);
363         calculated[2] = dataset[3]/dataset[5];
364         calculated[3] = dataset[6]/dataset[5];
365         calculated[4] = dataset[8]/dataset[5];
366         calculated[5] = dataset[9]/dataset[10];
367         calculated[6] = dataset[11]/dataset[5];
368         calculated[7] = dataset[12]/dataset[5];
369         return calculated;
370 }

在进行操作时,我遇到了以下警告,但我不理解它们的含义。

369:2: warning: return makes integer from pointer without a cast [enabled by default]
369:2: warning: function returns address of local variable [enabled by default]

我是否基本上漏掉了什么?请给我一些提示/解决方案。


返回类型必须是double *或类似的类型。 - tay10r
7
不要返回指向栈内存中分配的变量的指针。 - Mitch Wheat
1
你期望你的函数返回什么?目前它返回一个转换为int类型的数组指针。这个数组在栈上,所以它会在函数返回时消失,这就是为什么会有警告。无论如何,你的函数做了一些你不希望它做的事情。 - Grzegorz
这些警告非常明确和显而易见。你似乎有一些基本的误解,但由于你没有提供任何信息来说明为什么你认为错误不是完全明确和显而易见的,所以很难确定它们是什么。 - Jim Balter
3个回答

14
double calculated[8]

在栈上分配内存,当函数返回时将被解除绑定,因此对于调用函数来说无法安全访问。

相反,应使用

double* calculated = malloc(8 * sizeof(double));

将其分配到堆上,然后可以在程序中共享。

编辑

我不确定返回int的意图。如果要返回8个double的堆分配计算结果:

#include "stdlib.h"
// ...
double* calculation(double* dataset){
    double* calculated = (double*)malloc(8 * sizeof(double));
    calculated[0] = dataset[7]/dataset[5];
    // Other assignments ... 
    return calculated;
}

请注意,为了适应 double* 的返回,您的调用代码需要进行相应的调整。
根据Gauthier的评论,分配的数组所有权从“calculation”转移到调用函数,调用函数在不再需要时必须释放它。

2
and change the return type - tay10r
3
问题被标记为 C,因此请使用 malloc 而不是 new - Paul R
1
@pistal - 这是一个常见的问题 - 例如 这里 和 https://dev59.com/_Ggu5IYBdhLWcg3wOUck。简而言之 - 在不同的演示环境中,制表符的大小可能会有所不同。 - StuartLC
3
请不要在C语言中将malloc()的返回值转换类型。如果dataset是只读的,应该声明为const double * - unwind
2
值得一提的是,结果数组必须在应用程序中稍后释放!我认为最好在calculation函数外部定义结果数组,并传递指向它的指针double *calculation(double * const result, const double * const dataset)。您可能需要传递数组大小,但您似乎已经硬编码了它们。 - Gauthier
显示剩余7条评论

1

首先,您的函数返回类型不正确。它可能应该是一个指向双精度浮点数的指针。

其次,您正在返回分配在堆栈上的本地变量的地址,一旦从函数返回,该变量就会消失,同样也会消失它的地址。

因此,如果您真的想返回地址,则应使用:

double* calculated = malloc(sizeof(double)*8);

我离专业还很远呢! - Sankalp

1
你可以添加一个额外的参数,用于返回结果。
void calculation(double* dataset, double * result)

以下是调用函数的方法。
calculation(value_perf, calculated_val);

假设calculated_val已被声明为双精度数组,您可以方便地在同一表达式中的另一个函数中使用返回值,返回相同的参数。

double * calculation(double* dataset, double * result)
{
    ...
    return result;
}

更简洁,避免了可能出现的内存管理问题。然而,我认为返回result并没有用处,反而会造成混淆。作为这个函数的使用者,我会浪费时间去思考两者之间的区别。更有用的做法是返回一个int表示错误(如果没有错误则返回0,如果除数为0则返回其他错误代码等)。 - Gauthier
没错。除非使用明确,否则返回参数可能会令人困惑。一些库函数也使用这样的方案,例如fgets/strerror_r。fgets还通过返回NULL来指示错误。我总是喜欢编写像while (fgets(...) != NULL) ...fprintf("%s", strerror_r(...))这样的代码。 - user1969104

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接