首页 > 解决方案 > 是否可以从函数返回结构数组?

问题描述

这是我的第一个真正的编码课程,我可能在这里走错了路,但是对于 C 编程课程中的项目,我需要编写一个函数来从文件中读取各种数字并将它们分成类别:系数和指数。我想我已经完成了那部分,但是为了使用我读过的数字的内容,我试图将一个结构数组从一个函数传递给主函数,以便我可以使用这些内容。下面的代码是我现在所拥有的,它没有给我任何错误,但是当我在主函数中访问数组时,除了第一个值外,它是空的。有什么我可以改变来完成这项工作的吗?还是更好的解决方法?

任何帮助表示赞赏

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct exponential
{
    float coef;
    int expo;
    struct exponential *ptr_exp;
}EXPO;

EXPO** input_poly(EXPO *ex_array[], FILE *finput);

int main()
{
    FILE *finput;
    finput=fopen("cp7_in.txt","r");
    EXPO *ptr_array[2];
    EXPO **ptr, *ptr1, *ptr2, **ptraddress;
    ptr=(input_poly(ptr_array, finput));
}


EXPO** input_poly(EXPO *ptr_array[], FILE *finput)
{
    int count, string_size, offset1, offset2, offset3, offset4;
    char expo_string[64];
    char *expo_ptr, *string1, *string2;
    EXPO *ptr1, *ptr2;
    string1=(char*)malloc(sizeof(expo_string)+1);
    string2=(char*)malloc(sizeof(expo_string)+1);
    for(count=0;(fgets(expo_string,64,finput)>0)&&(count<2);count++)
    {
        if(count==0)
        {
            strcpy(string1,expo_string);
        }
        if(count==1)
        {
            strcpy(string2,expo_string);
        }
    }
    EXPO ex_array1[(sizeof(string1)/2)];
    EXPO ex_array2[(sizeof(string2)/2)];
    count=0;
    string_size=(sizeof(string1)/2);
    offset1=0;
    offset2=0;
    offset3=0;
    offset4=0;
    while(count<string_size)
    {
        sscanf((string1+offset2),"%e %d %n",&(ex_array1[count]).coef,&(ex_array1[count]).expo,&offset1);
        sscanf((string2+offset4),"%e %d %n",&(ex_array2[count]).coef,&(ex_array2[count]).expo,&offset3);
        (ex_array1[count]).ptr_exp=&(ex_array1[count+1]);
        (ex_array2[count]).ptr_exp=&(ex_array2[count+1]);
        count++;
        offset2+=offset1;
        offset4+=offset3;
    }
    ptr1=ex_array1;
    ptr2=ex_array2;
    ptr_array[0]=ptr1;
    ptr_array[1]=ptr2;
    free(string1);
    free(string2);
    return ptr_array;
 }

标签: c

解决方案


不,您不能从函数返回结构数组。从函数声明

In the declaration grammar of a function declaration, the type-specifier 
sequence, possibly modified by the declaration, designates the return type 
(which may be any type other than array or function type)...

函数返回的返回类型不能是数组,所以不能从函数返回数组。
解决这个问题的常用方法是返回一个指向第一个数组元素的指针:

struct arr_s {
    int arr_member;
};

struct arr_s *function_that_returns_array_of_5_ints(void) {
    static struct arr_s array[5] = {1,2,3,4,5};
    return arr; // 'Array to pointer conversion'
}

void some_function(void) {
    struct arr_s *arr = function_that_returns_array_of_5_ints();
    printf("%d\n", arr[3].arr_member);
}

有效的方式arr[3].arr_member是因为arr[3]转换为指针算术*(arr + 3)并且因为指针算术

- If the pointer P points at an element of an array with index I, then
  - P+N and N+P are pointers that point at an element of the same array with index I+N

现在,在您的代码中,查看这些片段,我添加了一些注释:

// ptr_array is declared in main and passed to this function,
// so it's storage duration is longer then this function
EXPO** input_poly(EXPO *ptr_array[], FILE *finput)
{
    ...
    // these variables are placed on stack, they have automatic storage duration
    EXPO ex_array1[(sizeof(string1)/2)];
    EXPO ex_array2[(sizeof(string2)/2)];
    ....
    ptr1=ex_array1;
    ptr2=ex_array2;
    ptr_array[0]=ptr1; // = ex_array1
    ptr_array[1]=ptr2; // = ex_array2
    ...
    return ptr_array; // the variables ex_array1 and ex_array2 stop existing here,
    // yet you return pointers to them in ptr_array[0] and ptr_array[1].
    // the memory allocated for ex_arrays does not exists after return
}

ex_array1并且是具有原子存储持续时间ex_array2的变量。这意味着,是:

automatic storage duration. The storage is allocated when the block 
in which the object was declared is entered and deallocated when it 
is exited by any means (goto, return, reaching the end).

(它们不是 VLA,因为(sizeof(string1)/2)它是一个常量表达式。无论如何,以下内容仍然适用)。由于分配给变量的内存在函数返回ex_array1ex_array2不复存在input_poly,你返回一个指向不存在的内存(已被释放的存储)的指针,你不能再访问 ex_arrays。
还要注意sizeof运算符。sizeof(expo_string)等于sizeof(char[60])等于 60。但是sizeof(string1)等于sizeof(char*),所以在 64 位机器上可能等于 8(可能不是,这取决于机器),所以实际上EXPO ex_array1[(sizeof(string1)/2)];你实际上正在做EXPO ex_array1[4];,而且string_size = 4;,可能那是'意图。
解决方案是使用 malloc 或使用静态存储持续时间声明 ex_arrays,或者在input_poly函数外部“全局”声明它们或使用static关键字。我认为,您能做的最好的事情是:

  EXPO *ex_array1 = malloc(sizeof(string1)/2);
  EXPO *ex_array2 = malloc(sizeof(string2)/2);

或者我猜你真的想做这样的事情:

  string_size = strlen(string1)/2; // get string length in string1 and divide by 2
  EXPO *ex_array1 = malloc(string_size);
  EXPO *ex_array2 = malloc(string_size);

这样,为 ex_arrays 分配的内存将在函数返回后继续存在,这样您仍然可以在其他函数中访问它。


推荐阅读