【问题标题】:How do I return a struct with dynamic multidimensional arrays in C?如何在 C 中返回具有动态多维数组的结构?
【发布时间】:2020-12-01 10:09:00
【问题描述】:

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

这是一个显示问题的示例程序:

#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, 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};
     
     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.f_array = (float*)malloc(i_length*sizeof(float*)); 必须是return_this_struct.f_array = (float*)malloc(i_length*sizeof(float));,或者更好的是return_this_struct.f_array = malloc(i_length*sizeof *return_this_struct.f_array);

标签: c multidimensional-array dynamic return structure


【解决方案1】:

在你的代码中

return_this_struct.lf_multi_array[0] = lf_dummy_0;

return_this_struct.lf_multi_array[1] = lf_dummy_1;

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

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

【讨论】:

    【解决方案2】:

    我的 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;
    }
    

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

    还注意到我使用的是双精度而不是浮点数。原因是它会比混合 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", i, 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", i, j,  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", i, j,  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", i, j,  arrayHolder -> multiArray[i][j]);
            }
        }
        
        for (int i = 0; i < arrayHolder -> rows; ++i){
            free(arrayHolder -> multiArray[i]);
        }
        free( arrayHolder -> multiArray);
        
        free(arrayHolder);
    
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      正如 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];
           }
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-24
          • 2020-03-23
          • 1970-01-01
          • 2021-04-21
          相关资源
          最近更新 更多