[英]Returning Array from function in C
出于某种原因,我的函数仅返回数组中的第一个元素,而我无法弄清数组其余部分为何超出范围。 该函数采用两个整数数组,将它们各自的元素相加,然后将总和放入返回的第三个数组中。
这是我的代码:
#include <stdio.h>
/* 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
第一行是函数内部的求和数组元素。 剩下的就是main()中发生的事情。
我想念什么?
*编辑* ANSWERED
谢谢大家的帮助! 我实际上是前一段时间学习过C和C ++的,但是最近开始回过头来微调我的知识。 真的感谢所有帮助。
主要的答案是
1)静态分配内存(使用static关键字)
2)动态分配内存(使用malloc())
3)将变量设为全局
4)将结果total()作为参数传递给函数,这样它就不会超出范围。
您正在为数组进行堆栈分配,并且当函数返回时,堆栈分配的存储将消失。 请改用堆分配。
更改
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));
问题在于,当sumarrays
返回时, total
组将不再存在 1 ,因此main
接收的指针值不再有效。 简而言之,您不能从这样的函数返回数组。
您有几种选择。
第一个(首选IMO是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
函数中声明它为static
来做到这一点:
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
int i;
static int total[10];
...
使用这种方法, total
数组将在程序启动时分配并保留,直到程序终止。 使此方法变得不太理想的原因是,您只有该total
组的单个实例,该实例在对sumarrays
所有调用中sumarrays
。 该功能不再可重入 ; 如果sumarrays
调用了另一个函数调用sumarrays
,则无论是第一个调用写入total
都会被第二个调用所破坏( strtok
库函数存在此问题,这在过去引起了很多sumarrays
)。 您的代码显然没有这个问题,但是需要注意。 如果没有必要,不要声明static
东西。
最后一个选项是sumarrays
为total
内存动态分配内存(如hacks和merlin2011的答案)。 这样可以避免重新输入的问题,但是现在您必须处理内存管理。 C不是您的母亲,也不会在您之后清理。因此,使用malloc
或calloc
分配的任何内存都必须使用free
2释放。
main
函数所花费的时间内已被覆盖。
我同意关于自动(堆栈)和堆内存的所有其他答案。 所有好的方法,但是堆栈上的全局变量也是一个选择 。 重要的是要注意, 并不是您选择使用堆栈内存,而是在范围上它是本地的 。 局部作用域自动变量在创建它们的函数返回时消失。 但是,全局范围的变量(也使用堆栈存储器存储)在程序运行期间有效,因此提供了另一种方法来解决您的问题...
一行更改将导致您的代码运行,将本地total
(自动范围)副本更改为全局副本:
int total[10];//Put this here, outside of any function block in same file, i.e. (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
将其保留在堆栈中,直到程序退出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.