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

时间:2018-05-09 08:02:19

标签: c

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

感谢任何帮助

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

1 个答案:

答案 0 :(得分:0)

不,您无法从函数返回结构数组。来自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_array2atomatic 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_array1函数返回后为变量ex_array2input_poly分配的内存不再存在,所以返回指向不存在的内存(已释放的存储空间)的指针,您可以&#39; t不再访问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,或者声明它们全局&#39;在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分配的内存将在函数返回后继续存在,这样你仍然可以在其他函数中访问它。