【问题标题】:an array for returning int in C programming在 C 编程中返回 int 的数组
【发布时间】:2021-12-26 00:28:45
【问题描述】:

我有一个关于从 C 中的函数返回数组的问题,我不知道为什么它总是将结果作为转储代码给出。请帮忙,我真的非常感谢你! 我设置了一个 int list3[size3] 但似乎我必须返回一个数组格式为 int*list3。所以我将另一个数组设置为 list4[size3] 以将 list3 复制到 list4 中。但我不确定这是导致代码转储的原因。如果是,请帮助我提供解决问题的建议。再次感谢您!

#include<stdio.h>

int* merged(int[], int[], int, int);
void sort(int[], int);

int main() {

    int size1;
    printf("Enter list1: ");
    scanf("%d", &size1);

    int list1[size1];

    for (int i = 0; i < size1; i++) {
        scanf("%d", &list1[i]);
    }

    int size2;
    printf("Enter list2: ");
    scanf("%d", &size2);

    int list2[size2];

    for (int i = 0; i < size2; i++) {
        scanf("%d", &list2[i]);
    }

    int* list3 = merged(list1, list2, size1, size2);

    printf("The merged list is: ");

    int size3 = size1 + size2;

    for (int i = 0; i < size3; i++) {
        printf("%d ", list3[i]);
    }

    printf("\n");
}

int* merged(int list1[], int list2[], int size1, int size2) {
    int list3[size1 + size2];
    for (int i = 0; i < size1; i++) {
        list3[i] = list1[i];
    }

    int count = size1;

    for (int i = 0; i < size2; i++) {
        list3[count] = list2[i];
        count++;
    }

    int size3 = size1 + size2;

    sort(list3, size3);

    int* list4;

    for (int i = 0; i < size3; i++) {
        list4[i] = list3[i];
    }

    return list3;
}

void sort(int list3[], int size3) {

    for (int i = 0; i < size3; i++) {
        int min = list3[i];
        int min_index = i;

        for (int j = i + 1; j < size3; j++) {
            if (list3[j] < min) {
                min = list3[j];
                min_index = j;
            }
        }

        if (min_index != i) {
            list3[min_index] = list3[i];
            list3[i] = min;
        }
    }
}

https://onlinegdb.com/-ChT7PA3w

【问题讨论】:

  • 您是否尝试过使用 gdb 之类的工具对其进行检查,并找到导致您出现 seg 错误的行和元素?此外,更好地缩进你的代码将有助于它的可读性
  • 您不能返回指向自动变量的指针(例如list3)。您不能使用尚未初始化的指针变量指向某个对象 (list4)。如果你想让一个函数返回一个数组,你基本上有两个选择:使用malloc动态分配数组或在调用者中创建数组并将其作为附加参数提供。

标签: arrays c return


【解决方案1】:

merge 返回指向本地数组的指针。它是 UB,因为该数组在函数返回时停止存在。所以返回的指针引用了一个无效的对象。

int *merged(const int * restrict list1, const int * restrict  list2, size_t size1, size_t size2) 
{
    int *result = NULL;
    int l1size = size1 * !!list1, l2size = size2 * !!list2;
    size_t newsize = l1size + l2size;

    if(newsize)
    {
        result = malloc(newsize * sizeof(*result));
        if(result)
        {
            if(l1size) memcpy(result, list1, l1size * sizeof(*result));
            if(l2size) memcpy(result + l1size, list2, l2size * sizeof(*result));
        }
    }
    return result;
}

void printList(const int * restrict list, size_t size)
{
    if(size && list)
    {
        for(size_t index = 0; index < size; index++)
            printf("[%2zu] = %3d\n", index, list[index]);
    }
}

void initList(int * restrict list, size_t size, int maxval)
{
    if(size && list)
    {
        for(size_t index = 0; index < size; index++)
            list[index] = rand() % maxval;
    }
}


int main() {

    size_t size1 = 20;
    size_t size2 = 10;
    int list1[size1], list2[size2];

    initList(list1, size1, 100);
    initList(list2, size2, 100);
    printList(list1, size1);
    printf("----------------\n");
    printList(list2, size2);
    printf("----------------\n");
    
    int *list3 = merged(list1, list2, size1, size2);
    printList(list3, size2 + size1);
    printf("----------------\n");

    free(list3);
}

还要使用正确的尺寸类型size_t

【讨论】:

    【解决方案2】:

    代码中的几个问题:

    第一:
    您正在从 merged() 函数返回 list3list3 是一个本地(自动)非静态变量,其生命周期仅限于其范围,即声明它的块。任何在其生命周期之外访问它的尝试都会导致undefined behaviour。此外,list3 是 VLA(可变长度数组),您不能将其声明为 static,因为 VLA 不能具有 static 存储持续时间。其他选项是将list3 声明为指向int 的指针,并为其动态分配内存。

    第二:
    merged() 中,您正在取消引用未初始化的指针list4。取消引用未初始化的指针是未定义的行为。将内存分配给list4,然后使用它。此外,为什么需要list4?您将list1list2 复制到list3 并从merged() 函数返回list3。我看不到list4 的任何用途。最好将其从 merged() 函数中删除。

    因此,您的代码中的merged() 只需进行一项更改:

    int*merged(int list1[], int list2[], int size1, int size2) {
        int * list3 = malloc ((size1 + size2) * sizeof (int));
        if (list3 == NULL) {
            //handle the allocation failure
            //I am exiting..
            printf ("Failed to allocate memory\n");
            exit (EXIT_FAILURE);
        }
        ....
        ....
        ....
        sort (list3, size3);
        // removed list4 from code
    
        return list3;
    }
    

    确保释放动态分配的内存。在main() 函数中,你应该这样做:

    int main (void) {
        ....
        ....
        ....
        for (int i = 0; i < size3; i++) {
            printf("%d ", list3[i]);
        }
    
        printf("\n");
        // free dynamically allocated memory
        free (list3);
    
        return 0;
    }
    

    几点,我留给你学习和实施:

    • 您的代码中存在一个严重问题,即您没有验证用户输入。尝试将size1size2 的值设为0 或负值或非常大的正值,然后检查会发生什么。适当地处理用户输入。另外,考虑一下,如果你真的需要 VLA(可变长度数组)或者你可以使用固定大小的数组。固定大小的数组可以是静态的。

    • 实施部分有改进的余地。尝试找出它们并进行改进。

    【讨论】:

    • 最好merged为合并列表分配内存。如果我们将这个责任从merged 中移开,那么内存可以自动分配到main,并将指向它的指针传递给merged。合并后的声明更像:int * merged(int * dest, int * list1, int * list1, size_t size1, size_t size2)
    • @Chris 在 C 中,函数分配内存并返回该内存的引用是完全正常的,这就是 merged() 函数正在做的事情 - 返回一个新列表,它是合并+排序的2 列表作为参数传递给它。除此之外,请阅读我帖子的最后一点,我已经明确提到实现部分有改进的范围,我将其留给 OP 以识别它并在他的代码中进行相应的更改。
    【解决方案3】:

    您不能在merged 中使用return list3,因为您要返回第一个元素(不是数组)的地址,但是一旦函数返回,整个list3 数组就会超出范围和生命周期,所以它是不再可用(并且指针指向不再有效的位置)您需要动态分配内存以允许数组在函数调用中生存,或使用全局变量(这使得函数不可重入)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      • 2012-04-12
      • 1970-01-01
      相关资源
      最近更新 更多