从C中的函数返回数组

由于某种原因,我的函数只返回我的数组中的第一个元素,我无法弄清楚为什么数组的其余部分超出范围。 该函数接受两个整数数组,添加它们各自的元素,并将总和放入返回的第三个数组中。

这是我的代码:

#include  /* count digits, white space, others */ int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len); void main() { int arr1[10]; size_t arr1len = 10; int arr2[10] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; size_t arr2len = 10; int i; int *x; arr1[0] = 2; arr1[1] = 3; arr1[2] = 2; arr1[3] = 2; arr1[4] = 2; arr1[5] = 2; arr1[6] = 3; arr1[7] = 2; arr1[8] = 2; arr1[9] = 2; //printf("%d\t%d\t%d\n", arr1, *arr1, *(arr1 + 1)); x = sumarrays(arr1, arr1len, arr2, arr2len); for (i = 0; i < 10; i++) { printf("Array1: %d\tArray 2: %d\tX = %d\n", arr1[i], arr2[i], x[i]); } //return 0; } int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) { int i; int total[10]; for (i = 0; i < 10; i++) { total[i] = *(arr1 + i) + *(arr2 + i); } for (i = 0; i < 10; i++) { printf("%d\t", total[i]); } printf("\n"); return total; } 

这是输出:

 4 5 4 4 4 4 5 4 4 4 Array1: 2 Array 2: 2 X = 4 Array1: 3 Array 2: 2 X = 1974388256 Array1: 2 Array 2: 2 X = -161927102 Array1: 2 Array 2: 2 X = 2686628 Array1: 2 Array 2: 2 X = 8670801 Array1: 2 Array 2: 2 X = 0 Array1: 3 Array 2: 2 X = 27 Array1: 2 Array 2: 2 X = 2686540 Array1: 2 Array 2: 2 X = 4 Array1: 2 Array 2: 2 X = 2686916 

第一行是函数内的sum数组元素。 剩下的就是main()中发生的事情。

我错过了什么?

*编辑* 答案

谢谢大家的帮助! 我实际上不久前学过C和C ++,但最近开始回过头来调整我的知识。 真的很感激所有的帮助。

主要答案是

1)静态分配内存(使用static关键字)

2)动态分配内存(使用malloc())

3)使变量成为全局变量

4)将结果total()作为参数传递给函数,使其不会超出范围。

问题是当sumarrays返回时, total不再存在 1 ,因此main接收的指针值不再有效。 简而言之,您不能从这样的函数返回数组。

你有几个选择。

第一个(和IMO首选选项)是将total数组作为参数之一传递,并使调用者负责留出足够的内存:

 void sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len, int *total, size_t totallen) { ... for (i = 0; i < totalLen; i++) { total[i] = *(arr1 + i) + *(arr2 + i); ... } #define ARRLEN 10 int main( void ) { ... int x[ARRLEN]; ... sumarrays( arr1, ARRLEN, arr2, ARRLEN, x, ARRLEN); 

在这种方法中,调用者( main )负责知道目标数组需要多大,并为其留出内存。 帮助 sumarrays函数与main 分离 ,因为它不必依赖于参数列表未明确指定的信息(例如数组大小)。 使用此方法,您不仅限于大小为10的数组。

第二种选择是声明total ,使其在sumarrays退出后不会消失。 您可以通过在文件范围内声明它(如在ryyker的答案中)或在sumarrays函数中声明它为staticsumarrays

 int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) { int i; static int total[10]; ... 

使用这种方法,将在程序启动时分配total组并保持直到程序终止。 这种方法不太可取的原因是你只有一个total数组的实例,它在所有对sumarrays调用中sumarrays 。 该function不再是可重入的 ; 如果sumarrays调用另一个调用sumarrays函数,那么无论第一次调用写入total都将被第二次调用破坏( strtok库函数有这个问题,这在过去引起了很多胃灼热)。 您的代码显然没有这个问题,但需要注意的是。 如果您不需要,请不要声明static

最后一个选项是sumarrays动态分配内存(如haccks'和merlin2011的答案)。 这避免了重入问题,但现在你必须处理内存管理。 C不是你的母亲,不会在你之后进行清理,所以你用malloccalloc分配的任何内存都必须以free 2发布。


从逻辑上讲,无论如何; 内存显然仍然存在,但它已经可供系统的其余部分使用,并且在程序返回main函数所花费的时间内被覆盖。

2.大多数平台将在程序退出时回收动态分配的内存,但少数(不可否认是较旧的,古怪的平台)可能不会。 此外,对于长时间运行的程序(服务器,守护程序等),您必须非常小心地释放您分配并且不再需要的任何内存,否则您最终会耗尽。

您正在为您的arrays进行堆栈分配,并且当函数返回时,堆栈分配的存储会消失。 请改用堆分配。

更改

int total[10];

int* total = malloc(10*sizeof(int))

当然,这意味着你必须在完成后free内存。 在这种情况下, return 0;之前return 0; 在主要,你需要

 free(x); 

我的函数只返回数组中的第一个元素,我无法弄清楚为什么数组的其余部分超出了范围。

不,它返回指向第一个元素的指针 – 整个数组超出范围。 您看到的任何数据都保留在函数中,这是运气而不是判断,并且您不能使用它,因为它被释放以供其他函数使用。

数组不是C中的第一类数据类型 – 您无法通过复制返回数组。

通常的解决方案是让调用者拥有该数组,并将其地址和大小传递给该函数。

 int* func( int* arr, int arrlen ) { // write to arr[0] to arr[arrlen-1] ; return arr ; } int main() { int array[256] ; func( array, sizeof(arr)/sizeof*(*arr) ) ; } 

其他不太常见且通常不明智的可能性是要么返回包含数组的结构(结构是第一类数据类型),但要做到这一点在许多情况下效率有点低,或者在函数内动态分配数组,但这不是一个特别好的主意,因为调用者有责任释放内存并且可能不知道这个责任 – 这是内存泄漏的一个秘诀。

您不能返回指向自动局部变量的指针。 total是一个自动局部变量,在执行函数体后不存在。

可以返回指向static局部变量或动态分配变量的指针。 更改
int total[10];

 int *total = malloc(10 * sizeof(int)); 

我同意关于自动(堆栈)和堆内存的所有其他答案。 所有好方法,但堆栈上的全局变量也是一种选择 。 重要的是要注意, 并不是您选择使用堆栈内存,而是它在本地范围内 。 当创建它们的函数返回时,本地范围的自动变量会死亡。 但是,全局范围的变量(也使用堆栈内存存储)在程序的持续时间内存在,因此提供了另一种方法来解决您的问题……

一行更改将导致代码运行,将您的本地副本(自动范围)更改为全局:

 int total[10];//Put this here, outside of any function block in same file, ie (will give it global scope) //note, commented this in function below int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) { int i; //int total[10];//move this to global scope for (i = 0; i < 10; i++) { total[i] = *(arr1 + i) + *(arr2 + i); } for (i = 0; i < 10; i++) { printf("%d\t", total[i]); } printf("\n"); return total; } 

通过这种方法 ,全局范围的变量可以让您的回报获得成功。 数组total使其保持在堆栈中,直到程序退出。