【问题标题】:C: Initializing a dynamic array inside a structC:初始化结构内的动态数组
【发布时间】:2013-09-10 08:53:30
【问题描述】:

我正在尝试在 C 中实现我自己的基本版本的矩阵乘法,并基于另一种实现,我制作了一个矩阵数据类型。代码有效,但作为一个 C 新手,我不明白为什么。

问题:我有一个结构,里面有一个动态数组,我正在初始化指针。见下文:

// Matrix data type
typedef struct
{
    int rows, columns;      // Number of rows and columns in the matrix
    double *array;          // Matrix elements as a 1-D array
} matrix_t, *matrix;

// Create a new matrix with specified number of rows and columns
// The matrix itself is still empty, however
matrix new_matrix(int rows, int columns)
{
    matrix M = malloc(sizeof(matrix_t) + sizeof(double) * rows * columns);
    M->rows = rows;
    M->columns = columns;
    M->array = (double*)(M+1); // INITIALIZE POINTER
    return M;
}

为什么需要将数组初始化为(double*)(M+1)?似乎 (double*)(M+100) 也可以,但是例如(double *)(M+10000) 不再起作用,当我运行我的矩阵乘法函数时。

【问题讨论】:

  • 请:不要在一个typedef中声明两种类型,不要在typedef中隐藏指针类型,不要使用带有_t的名称,它们是POSIX保留的,使用size_t对于rowscolums
  • 不,_t 不是为 POSIX 保留的。它实际上不是为任何东西保留的。虽然,应该只在类型名称中使用它。例如,size_t 不是 POSIX。

标签: c arrays dynamic struct initialization


【解决方案1】:

M+1 指向紧跟在M 之后的内存(即跟在两个intdouble* 之后)。这是您为矩阵数据分配的内存:

matrix M = malloc(sizeof(matrix_t) + sizeof(double) * rows * columns);
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

使用M+100M+10000 然后尝试填充矩阵将导致undefined behaviour。这可能会导致程序崩溃,或者程序似乎可以运行(但实际上已损坏),或者介于两者之间。

【讨论】:

    【解决方案2】:

    你需要初始化它,否则(等待它)它是未初始化的

    你不能将未初始化的指针用于任何事情,除非产生未定义的行为。

    将其初始化为M + 1 完全正确,而且代码非常好。任何其他值都无法使用您为此确切目的分配的内存。

    我的意思是,结构末尾的 double * 不会“自动”指向此内存,这是对您的问题的隐含信念,为什么它应该被初始化。因此,它必须设置为正确的地址。

    【讨论】:

      【解决方案3】:

      这种东西的推荐方法是与offsetof结合使用的unsized array。它确保正确对齐。

      #include <stddef.h>
      #include <stdlib.h>
      
      // Matrix data type
      typedef struct s_matrix
      {
          int rows, columns;      // Number of rows and columns in the matrix
          double array[];         // Matrix elements as a 1-D array
      } matrix;
      
      // Create a new matrix with specified number of rows and columns
      // The matrix itself is still empty, however
      matrix* new_matrix(int rows, int columns)
      {
          size_t size = offsetof(matrix_t, array) + sizeof(double) * rows * columns;
          matrix* M = malloc(size);
          M->rows = rows;
          M->columns = columns;
          return M;
      }
      

      【讨论】:

      • 谢谢你,我同意不要在 typdef 中隐藏指针类型更有意义,正如 Jens 所指出的那样。但是,我认为您想采用 offsetof(matrix, array),因为 matrix_t 未在您的代码中定义...
      • 向数组添加数据的正确方法是什么?我在第一版代码中使用的旧方法不再起作用。无论我尝试什么,我都会得到“错误:对灵活数组成员的无效使用”。
      • 哦,这个简单的事情似乎奏效了。但是,我在同时设置数组的所有值时遇到问题。以前我写过matrix* A = new_matrix(3, 2); double amatrix[] = { 3, 2, 8, 1, 9, 2 }; A-&gt;array = amatrix;,但现在已经不行了。
      • 这段代码不填充数组,它用于更改指针(使您在结构之后分配的所有内存都无用)。要复制数组的内容,请使用memcpy()
      猜你喜欢
      • 1970-01-01
      • 2014-10-07
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 2022-12-03
      • 1970-01-01
      相关资源
      最近更新 更多