[英]Returning Array from function in C
For some reason, my function is only returning the first element in my array and I cannot figure out why the rest of the array goes out of scope. 出于某种原因,我的函数仅返回数组中的第一个元素,而我无法弄清数组其余部分为何超出范围。 The function takes two integer arrays, adds their respective elements, and puts the sum into a third array which is returned.
该函数采用两个整数数组,将它们各自的元素相加,然后将总和放入返回的第三个数组中。
Here is my code: 这是我的代码:
#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;
}
Here is the output: 这是输出:
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
The first line is the sum array elements from within the function. 第一行是函数内部的求和数组元素。 The remainder is what happens in the main().
剩下的就是main()中发生的事情。
What am I missing? 我想念什么?
*edit* ANSWERED *编辑* ANSWERED
Thank you everyone for the help! 谢谢大家的帮助! I actually learned C and C++ a while ago but have recently started to go back and fine tune my knowledge.
我实际上是前一段时间学习过C和C ++的,但是最近开始回过头来微调我的知识。 Really appreciate all the help.
真的感谢所有帮助。
The main answers were 主要的答案是
1) Statically allocate memory (using the static keyword) 1)静态分配内存(使用static关键字)
2) Dynamically allocate memory (using malloc()) 2)动态分配内存(使用malloc())
3) Make the variable global 3)将变量设为全局
4) Pass the result total() as an argument to the function so it doesn't go out of scope. 4)将结果total()作为参数传递给函数,这样它就不会超出范围。
You are doing stack allocation for your array, and stack-allocated storage goes away when a function returns. 您正在为数组进行堆栈分配,并且当函数返回时,堆栈分配的存储将消失。 Use heap allocation instead.
请改用堆分配。
Change 更改
int total[10];
to 至
int* total = malloc(10*sizeof(int))
. int* total = malloc(10*sizeof(int))
。
of course, that means you must also free
the memory after you are done with it. 当然,这意味着您还必须在完成处理后
free
内存。 In this case, before the return 0;
在这种情况下,在
return 0;
之前return 0;
in main, you need to 总的来说,你需要
free(x);
my function is only returning the first element in my array and I cannot figure out why the rest of the array goes out of scope.
我的函数仅返回数组中的第一个元素,而我无法弄清数组其余部分为何超出范围。
No, it returns a pointer to the first element - and the entire array goes out of scope. 不,它返回指向第一个元素的指针- 整个数组超出范围。 Any data you see that happens to remain as it was in the function is by luck rather than judgement, and you cannot use it as it is released for use by other functions.
您看到的任何碰巧保留在函数中的数据都是靠运气而不是判断,您不能使用它,因为它已发布供其他函数使用。
Arrays are not first class data types in C - you cannot return an array by copy. 数组不是C语言中的一流数据类型 -您不能通过副本返回数组。
The normal solution is to have the array owned by the caller and to pass its address and size to the function. 通常的解决方案是让调用者拥有该数组,并将其地址和大小传递给该函数。
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) ) ;
}
Other less common and generally ill-advised possibilities are either to return a struct containing the array (a struct is a first class data type), but to do that is somewhat inefficient in many cases, or to dynamically allocate the array within the function, but it is not a particularly good idea since the caller has the responsibility of freeing that memory and may not be aware of that responsibility - it is a recipe for a memory leak. 其他不太常见且通常不建议使用的可能性是返回包含数组的结构(结构是第一类数据类型),但是这样做在许多情况下效率低下,或者在函数内动态分配数组,但这不是一个特别好的主意,因为调用者有责任释放该内存,并且可能不知道该职责-这是导致内存泄漏的原因。
You can't return a pointer to an automatic local variable . 您不能返回指向自动局部变量的指针。
total
is an automatic local variable and it doesn't exist after function body executed. total
是一个自动局部变量,在函数体执行后不存在。
Pointer to static
local variable or dynamically allocated variable can be returned. 可以返回指向
static
局部变量或动态分配的变量的指针。 Change 更改
int total[10];
to 至
int *total = malloc(10 * sizeof(int));
The problem is that when sumarrays
returns, the total
array ceases to exist 1 , so the pointer value that main
receives is no longer valid. 问题在于,当
sumarrays
返回时, total
组将不再存在 1 ,因此main
接收的指针值不再有效。 In short, you cannot return arrays from a function like this. 简而言之,您不能从这样的函数返回数组。
You have several options. 您有几种选择。
The first (and IMO the preferred option) is to pass the total
array as one of your parameters, and make the caller responsible for setting aside enough memory: 第一个(首选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);
In this method, the caller ( main
) is responsible for knowing how big the target array needs to be and setting aside the memory for it. 在此方法中,调用方(
main
)负责知道目标数组需要多大,并为其预留内存。 The helps decouple the sumarrays
function from main
because it doesn't have to rely on information that isn't explicitly specified by the parameter list (such as the array sizes). 帮助可以将
sumarrays
函数与main
分离 ,因为它不必依赖未由参数列表明确指定的信息(例如数组大小)。 With this approach, you're not limited to arrays of size 10. 使用这种方法,您不仅限于大小为10的数组。
A second option is to declare total
such that it doesn't go away after sumarrays
exits. 第二种选择是声明
total
,以使sumarrays
退出后不会消失。 You can do this by either declaring it at file scope (as in ryyker's answer), or by declaring it static
within the sumarrays
function: 您可以通过在文件范围内声明它(如ryyker的回答),或在
sumarrays
函数中声明它为static
来做到这一点:
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
int i;
static int total[10];
...
With this approach, the total
array will be allocated at program startup and held until the program terminates. 使用这种方法,
total
数组将在程序启动时分配并保留,直到程序终止。 What makes this approach less desireable is that you have only a single instance of that total
array, which is shared across all calls to sumarrays
. 使此方法变得不太理想的原因是,您只有该
total
组的单个实例,该实例在对sumarrays
所有调用中sumarrays
。 The function is no longer re-entrant ; 该功能不再可重入 ; if
sumarrays
called another function that called sumarrays
, then whatever the first call had written to total
would be clobbered by the second call (the strtok
library function has this problem, which has caused much heartburn in the past). 如果
sumarrays
调用了另一个函数调用sumarrays
,则无论是第一个调用写入total
都会被第二个调用所破坏( strtok
库函数存在此问题,这在过去引起了很多sumarrays
)。 Your code obviously doesn't have this problem, but it's something to be aware of. 您的代码显然没有这个问题,但是需要注意。 Don't declare things
static
if you don't have to. 如果没有必要,不要声明
static
东西。
The final option is for sumarrays
to allocate the memory for total
dynamically (as in haccks' and merlin2011's answers). 最后一个选项是
sumarrays
为total
内存动态分配内存(如hacks和merlin2011的答案)。 That avoids the re-entrancy issue, but now you have to deal with memory management. 这样可以避免重新输入的问题,但是现在您必须处理内存管理。 C isn't your mother and won't clean up after you, so any memory you allocate with
malloc
or calloc
you have to release with free
2 . C不是您的母亲,也不会在您之后清理。因此,使用
malloc
或calloc
分配的任何内存都必须使用free
2释放。
main
function.
main
函数所花费的时间内已被覆盖。
I agree with every other answer regarding automatic (stack) and heap memory. 我同意关于自动(堆栈)和堆内存的所有其他答案。 All good approaches, however global variables on the stack are also an option .
所有好的方法,但是堆栈上的全局变量也是一个选择 。 It is important to note that it was not that you chose to use stack memory, but that it was also local in scope .
重要的是要注意, 并不是您选择使用堆栈内存,而是在范围上它是本地的 。 Locally scoped automatic variables die when the function that created them returns.
局部作用域自动变量在创建它们的函数返回时消失。 However, globally scoped variables, also stored using stack memory, live for the duration of your program, and therefore provide an alternative approach to solve your problem...
但是,全局范围的变量(也使用堆栈存储器存储)在程序运行期间有效,因此提供了另一种方法来解决您的问题...
A one line change will result in your code running, change your local copy of total
(automatic scope) to a global: 一行更改将导致您的代码运行,将本地
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;
}
With this approach , global scope of variable allows your return to be successful. 使用这种方法 ,变量的全局范围可以使您的返回成功。 The array
total
keeps it's existence on stack until program exits. 数组
total
将其保留在堆栈中,直到程序退出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.