简体   繁体   English

从C函数返回数组

[英]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). 最后一个选项是sumarraystotal内存动态分配内存(如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不是您的母亲,也不会在您之后清理。因此,使用malloccalloc分配的任何内存都必须使用free 2释放。


1. Logically speaking, anyway; 1.从逻辑上讲,无论如何; the memory is obviously still there, but it's been made available for the rest of the system to use, and has been overwritten in the time it took for your program to return to the main function. 内存显然仍然存在,但是已经可供系统的其余部分使用,并且在程序返回到main函数所花费的时间内已被覆盖。

2. Most platforms will reclaim dynamically allocated memory when the program exits, but a few (admittedly older, oddball platforms) may not. 2.大多数平台会在程序退出时回收动态分配的内存,但有些平台(可能是较旧的奇怪的平台)可能不会。 Also, for long-running programs (servers, daemons, etc.), you have to be very careful to release any memory you allocated and no longer need, otherwise you will eventually run out. 另外,对于长时间运行的程序(服务器,守护程序等),您必须非常小心释放分配的且不再需要的任何内存,否则最终将用光。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM