c - 是否可以从函数返回结构体数组?

标签 c

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

感谢任何帮助

#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;
 }

最佳答案

不,您不能从函数返回结构数组。来自 function declaration :

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)因为pointer arithmetic :

- 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_array1ex_array2是带有 atomatic storage duration 的变量。这意味着:

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_array2input_poly 返回后不复存在函数,您返回一个指向不存在的内存(已被释放的存储)的指针,您将无法再访问 ex_arrays。
另请关注sizeof运算符(operator)。 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 分配的内存将在函数返回后继续存在,这样您仍然可以在其他函数中访问它。

关于c - 是否可以从函数返回结构体数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50248382/

相关文章:

c++ - 将 FILE * 或 HANDLE 转换(分配)到 Windows 中的 IStream

c++ - 将结构的一部分分配给c中的另一个结构

c - Scanf 不等待输入

c - 错误取消引用指向 c 中不完整类型的指针

C - 如何在 for 循环中仅打印最大的数字?

使用 tar 查找差异的 c 代码

c++ - 使用 Visual Studio 2008 从 x86 编译 x64 dll

c - 当从另一个包导出 C 头函数时,将 C 头函数导入到 R 包中的正确方法是什么?

c - 输入、输出 C 程序

c - 嵌入式系统调试——我应该使用输出/日志文件吗?