如何在C中返回具有动态多维数组的结构?

问题描述

我遇到以下问题:“如果尝试返回具有动态多维数组的结构,则会丢失该数组内部的数据。如果使用指针返回该结构,则会遇到相同的问题。在某些情况下,我会遇到同样的问题。在数组中具有预期数据的位置” ->如何返回包含动态多维数组的结构? ->我的错误在哪里?

以下是显示问题的示例程序:

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

struct just_a_structure
        {
         double **lf_multi_array;
         float   *f_array;
        };

struct just_a_structure get_struct(int i_length)
    {
     struct just_a_structure return_this_struct;
     return_this_struct.lf_multi_array  = (double**)malloc(i_length*sizeof(double*));
     return_this_struct.f_array         = (float*)malloc(i_length*sizeof(float*));

     double lf_dummy_0[10] = {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9};
     double lf_dummy_1[10] = {1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9};

     return_this_struct.lf_multi_array[0] = lf_dummy_0;
     return_this_struct.f_array[0]       = 0.00;

     return_this_struct.lf_multi_array[1] = lf_dummy_1;
     return_this_struct.f_array[1]       = 0.01;    
    
     printf("\n output in function \n");
     printf("ma[0][0] %f \n",return_this_struct.lf_multi_array[0][0]);
     printf("ma[0][1] %f \n",return_this_struct.lf_multi_array[0][1]);
     printf("ma[0][2] %f \n",return_this_struct.lf_multi_array[0][2]);
     printf("ma[0][3] %f \n",return_this_struct.lf_multi_array[0][3]);
     printf("ma[0][4] %f \n",return_this_struct.lf_multi_array[0][4]);
     printf("ma[0][5] %f \n",return_this_struct.lf_multi_array[0][5]);
     printf("ma[0][6] %f \n",return_this_struct.lf_multi_array[0][6]);
     printf("ma[0][7] %f \n",return_this_struct.lf_multi_array[0][7]);
     printf("ma[0][8] %f \n",return_this_struct.lf_multi_array[0][8]);
     printf("ma[0][9] %f \n",return_this_struct.lf_multi_array[0][9]);
     printf("a[0] %f \n",return_this_struct.f_array[0]);
     
     printf("\n \n");
     printf("ma[1][0] %f \n",return_this_struct.lf_multi_array[1][0]);
     printf("ma[1][1] %f \n",return_this_struct.lf_multi_array[1][1]);
     printf("ma[1][2] %f \n",return_this_struct.lf_multi_array[1][2]);
     printf("ma[1][3] %f \n",return_this_struct.lf_multi_array[1][3]);
     printf("ma[1][4] %f \n",return_this_struct.lf_multi_array[1][4]);
     printf("ma[1][5] %f \n",return_this_struct.lf_multi_array[1][5]);
     printf("ma[1][6] %f \n",return_this_struct.lf_multi_array[1][6]); 
     printf("ma[1][7] %f \n",return_this_struct.lf_multi_array[1][7]); 
     printf("ma[1][8] %f \n",return_this_struct.lf_multi_array[1][8]); 
     printf("ma[1][9] %f \n",return_this_struct.lf_multi_array[1][9]);
     printf("a[1] %f \n",return_this_struct.f_array[1]);
    
     return return_this_struct;
    }
    
    
int main()
    {    
     int i_length = 500;
     
     struct just_a_structure returned_struct;
    
     returned_struct = get_struct(i_length);
    
     printf("\n output in main \n");
     printf("ma[0][0] %f \n",returned_struct.lf_multi_array[0][0]);
     printf("ma[0][1] %f \n",returned_struct.lf_multi_array[0][1]);
     printf("ma[0][2] %f \n",returned_struct.lf_multi_array[0][2]);
     printf("ma[0][3] %f \n",returned_struct.lf_multi_array[0][3]);
     printf("ma[0][4] %f \n",returned_struct.lf_multi_array[0][4]);
     printf("ma[0][5] %f \n",returned_struct.lf_multi_array[0][5]);
     printf("ma[0][6] %f \n",returned_struct.lf_multi_array[0][6]);
     printf("ma[0][7] %f \n",returned_struct.lf_multi_array[0][7]);
     printf("ma[0][8] %f \n",returned_struct.lf_multi_array[0][8]);
     printf("ma[0][9] %f \n",returned_struct.lf_multi_array[0][9]);
     printf("a[0] %f \n",returned_struct.f_array[0]);
     
     printf("\n \n");
     printf("ma[1][0] %f \n",returned_struct.lf_multi_array[1][0]);
     printf("ma[1][1] %f \n",returned_struct.lf_multi_array[1][1]);
     printf("ma[1][2] %f \n",returned_struct.lf_multi_array[1][2]);
     printf("ma[1][3] %f \n",returned_struct.lf_multi_array[1][3]);
     printf("ma[1][4] %f \n",returned_struct.lf_multi_array[1][4]);
     printf("ma[1][5] %f \n",returned_struct.lf_multi_array[1][5]);
     printf("ma[1][6] %f \n",returned_struct.lf_multi_array[1][6]); 
     printf("ma[1][7] %f \n",returned_struct.lf_multi_array[1][7]); 
     printf("ma[1][8] %f \n",returned_struct.lf_multi_array[1][8]); 
     printf("ma[1][9] %f \n",returned_struct.lf_multi_array[1][9]);
     printf("a[1] %f \n",returned_struct.f_array[1]);

     return 0;
    }

这是程序的输出

 output in function
ma[0][0] 0.000000
ma[0][1] 0.100000
ma[0][2] 0.200000
ma[0][3] 0.300000
ma[0][4] 0.400000
ma[0][5] 0.500000
ma[0][6] 0.600000
ma[0][7] 0.700000
ma[0][8] 0.800000
ma[0][9] 0.900000
a[0] 0.000000


ma[1][0] 1.000000
ma[1][1] 1.100000
ma[1][2] 1.200000
ma[1][3] 1.300000
ma[1][4] 1.400000
ma[1][5] 1.500000
ma[1][6] 1.600000
ma[1][7] 1.700000
ma[1][8] 1.800000
ma[1][9] 1.900000
a[1] 0.010000

 output in main
ma[0][0] 27471811305989270000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[0][1] 27471811305989273000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[0][2] 24361411570075108000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[0][3] 22932960320429427000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[0][4] 0.000000
ma[0][5] 0.000000
ma[0][6] 23754367043167420000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[0][7] 27471811305989273000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[0][8] -519591837366427200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000 
ma[0][9] 0.000000
a[0] 0.000000


ma[1][0] 21266032917854245000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[1][1] 21427427439475540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[1][2] 0.000000
ma[1][3] 0.000000
ma[1][4] 0.000000
ma[1][5] 0.000000
ma[1][6] 22334679298120726000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[1][7] -1.#QNAN0
ma[1][8] 23669996832223273000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
ma[1][9] 0.000000
a[1] 0.010000

我试图实现@Etini和@Sourav Ghost提供的解决方案。但是知道程序启动后立即崩溃。

     return_this_struct.lf_multi_array[0] = (double*)malloc(10*sizeof(double));
     return_this_struct.lf_multi_array[1] = (double*)malloc(10*sizeof(double));
     return_this_struct.f_array           = (float*)malloc(i_length*sizeof(float*));

     double lf_dummy_0[10] = {0.0,1.9};
     
     for(int i = 0; i < 10; i++)
        {
         return_this_struct.lf_multi_array[0][i] = lf_dummy_0[i];
        }
     for(int i = 0; i < 10; i++)
        {
         return_this_struct.lf_multi_array[1][i] = lf_dummy_1[i];
        }
        
     return_this_struct.f_array[0]       = 0.00;
     return_this_struct.f_array[1]       = 0.01;    
    ```

解决方法

在您的代码中

return_this_struct.lf_multi_array[0] = lf_dummy_0;

return_this_struct.lf_multi_array[1] = lf_dummy_1;

两者都在指针中存储了局部变量的地址,因此,一旦从被调用函数返回,这些局部变量就会超出范围,并且您正在访问无效的内存,从而产生不确定的行为。

如果要返回值,请为数组分配内存,然后复制单个元素值。

,

正如Sourav Ghost所说,您需要分配和复制单个元素,这就是我使它适用于第一个数组的方式

 return_this_struct.lf_multi_array[0] = (double*) malloc(10*sizeof(double));
     for(int i = 0; i < 10; i++){
         return_this_struct.lf_multi_array[0][i] = lf_dummy_0[i];
     }
,

我的C生锈了,请耐心等待。

这两行正在创建一个堆栈存储器,退出该函数时将删除该堆栈存储器:

double lf_dummy_0[10] = {0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9};
double lf_dummy_1[10] = {1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9};

这两行并未按照您的想法将存储在lf_dummy_0lf_dummy_0中的值复制到您的multi_array中。

return_this_struct.lf_multi_array[0] = lf_dummy_0;
...
return_this_struct.lf_multi_array[1] = lf_dummy_1;

现在,我们如何将您的问题分解成碎片?

首先,让我们编写一个方法,该方法将返回单个值数组,并确保在函数结束后可以访问这些值。

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

double *getPointerToArrayWithValues(int capacity){
    double * array = (double *) malloc(sizeof(double) * capacity);    

    double value = 0.0;
    for (int i = 0; i < capacity; ++i){
        array[i] = value;
        value += 0.1;
    }
    
    return array;
}

int main()
{
    int size = 10;
    double * array = getPointerToArrayWithValues(size);
    for (int i = 0; i < size; ++i){
        printf("arra[%d]: %f\n",i,array[i]);
    }
    free(array);
    return 0;
}

您可能会注意到,在获得值并显示它们之后,我正在释放我们使用的内存。我们必须自己清理。

还请注意,我使用的是double而不是float。原因是,晚于混合使用float和double会更容易使用它。

第二,让我们看看是否可以创建一个或多个数组。多阵列。

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

double **getPointerToMultiArrayWithValues(int rowCapacity,int columnCapacity){
    // Add space for rows
    double ** multiArray = (double **) malloc(sizeof(double * ) * rowCapacity);
     
    // Add space for columns
    for(int i = 0; i < rowCapacity; ++i){
        multiArray[i] = (double *) malloc(sizeof(double *) * columnCapacity);   
    }
    
    double value = 0.0;
    for (int row = 0; row < rowCapacity; ++row){
        for (int column = 0; column < columnCapacity; ++column){
            multiArray[row][column] = value;
            value += 0.1;
        }
    }
    
    return multiArray;
}

int main()
{
    int numberOfArrayToHold = 10;
    int sizeOfEachArray = 10;
    double ** multiArray = getPointerToMultiArrayWithValues(numberOfArrayToHold,sizeOfEachArray);
    
    for(int i = 0; i < numberOfArrayToHold; ++i){
        for (int j = 0; j < sizeOfEachArray; ++j){
            printf("multiArray[%d][%d]: %f\n",j,multiArray[i][j]);
        }
    }

    // Lets be grown up and clean after ourselves
    for (int i = 0; i < numberOfArrayToHold; ++i){
        free(multiArray[i]);
    }
    free(multiArray);

    return 0;
}

现在,您已经解决了如何创建一个数组和一个多数组(在本例中为双数组)的问题,我们可以集中精力创建一个可以容纳该数组的结构:

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

struct ArrayHolder{
  int rows;
  int columns;
  double ** multiArray;
};

double **getPointerToMultiArrayWithValues(int rowCapacity,int columnCapacity){
    // Add space for rows
    double ** multiArray = (double **) malloc(sizeof(double * ) * rowCapacity);
     
    // Add space for columns
    for(int i = 0; i < rowCapacity; ++i){
        multiArray[i] = (double *) malloc(sizeof(double *) * columnCapacity);   
    }
    
    double value = 0.0;
    for (int row = 0; row < rowCapacity; ++row){
        for (int column = 0; column < columnCapacity; ++column){
            multiArray[row][column] = value;
            value += 0.1;
        }
    }
    
    return multiArray;
}

int main()
{
    struct ArrayHolder arrayHolder;
    arrayHolder.rows = 10;
    arrayHolder.columns = 10;
    arrayHolder.multiArray = getPointerToMultiArrayWithValues(arrayHolder.rows,arrayHolder.columns);
    
    for(int i = 0; i < arrayHolder.rows; ++i){
        for (int j = 0; j < arrayHolder.columns; ++j){
            printf("multiArray[%d][%d]: %f\n",arrayHolder.multiArray[i][j]);
        }
    }
    
    for (int i = 0; i < arrayHolder.rows; ++i){
        free(arrayHolder.multiArray[i]);
    }
    free( arrayHolder.multiArray);

    return 0;
}

但是,我们希望返回一个结构,不是吗?然后,

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

struct ArrayHolder{
  int rows;
  int columns;
  double ** multiArray;
};

double **getPointerToMultiArrayWithValues(int rowCapacity,int columnCapacity){
    // Add space for rows
    double ** multiArray = (double **) malloc(sizeof(double * ) * rowCapacity);
     
    // Add space for columns
    for(int i = 0; i < rowCapacity; ++i){
        multiArray[i] = (double *) malloc(sizeof(double *) * columnCapacity);   
    }
    
    double value = 0.0;
    for (int row = 0; row < rowCapacity; ++row){
        for (int column = 0; column < columnCapacity; ++column){
            multiArray[row][column] = value;
            value += 0.1;
        }
    }
    
    return multiArray;
}

struct ArrayHolder getStructWithArray(){
    struct ArrayHolder arrayHolder;
    arrayHolder.rows = 10;
    arrayHolder.columns = 10;
    arrayHolder.multiArray = getPointerToMultiArrayWithValues(arrayHolder.rows,arrayHolder.columns);
    return arrayHolder;
}

int main()
{
   
    struct ArrayHolder arrayHolder = getStructWithArray(); 
    for(int i = 0; i < arrayHolder.rows; ++i){
        for (int j = 0; j < arrayHolder.columns; ++j){
            printf("multiArray[%d][%d]: %f\n",arrayHolder.multiArray[i][j]);
        }
    }
    
    for (int i = 0; i < arrayHolder.rows; ++i){
        free(arrayHolder.multiArray[i]);
    }
    free( arrayHolder.multiArray);

    return 0;
}

在这种情况下,我们将按值返回结构(复制)

但是,我们也可以通过指针来做到这一点!

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

struct ArrayHolder{
  int rows;
  int columns;
  double ** multiArray;
};

double **getPointerToMultiArrayWithValues(int rowCapacity,int columnCapacity){
    // Add space for rows
    double ** multiArray = (double **) malloc(sizeof(double * ) * rowCapacity);
     
    // Add space for columns
    for(int i = 0; i < rowCapacity; ++i){
        multiArray[i] = (double *) malloc(sizeof(double *) * columnCapacity);   
    }
    
    double value = 0.0;
    for (int row = 0; row < rowCapacity; ++row){
        for (int column = 0; column < columnCapacity; ++column){
            multiArray[row][column] = value;
            value += 0.1;
        }
    }
    
    return multiArray;
}

struct ArrayHolder * getPointerToStructWithArray(){
    struct ArrayHolder* arrayHolder = (struct ArrayHolder *) malloc(sizeof(struct ArrayHolder));
    arrayHolder -> rows = 10;
    arrayHolder -> columns = 10;
    arrayHolder -> multiArray = getPointerToMultiArrayWithValues(arrayHolder -> rows,arrayHolder -> columns);
    return arrayHolder;
}

int main()
{
   
    struct ArrayHolder * arrayHolder = getPointerToStructWithArray(); 
    for(int i = 0; i < arrayHolder -> rows; ++i){
        for (int j = 0; j < arrayHolder -> columns; ++j){
            printf("multiArray[%d][%d]: %f\n",arrayHolder -> multiArray[i][j]);
        }
    }
    
    for (int i = 0; i < arrayHolder -> rows; ++i){
        free(arrayHolder -> multiArray[i]);
    }
    free( arrayHolder -> multiArray);
    
    free(arrayHolder);

    return 0;
}

让我知道这是否对您有所帮助。

,

在使用循环分配值之前,您必须像这样分配数组 return_this_struct.lf_multi_array[0] = (double*) malloc(10*sizeof(double));