繁体   English   中英

从C函数返回数组

[英]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东西。

最后一个选项是sumarraystotal内存动态分配内存(如hacks和merlin2011的答案)。 这样可以避免重新输入的问题,但是现在您必须处理内存管理。 C不是您的母亲,也不会在您之后清理。因此,使用malloccalloc分配的任何内存都必须使用free 2释放。


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

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

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

一行更改将导致您的代码运行,将本地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.

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