在动态矩阵上设置指针

我正在尝试制作1字节元素的动态大小矩阵。 为此,我定义了以下function。 当我尝试将矩阵的第一个“nrows”元素设置为指向相应的行时(因此我可以执行矩阵[i] [j])时出现问题。 看起来像matrix[i] = matrix[nrows + i * single_row_elements_bytes]; 不能正常工作(程序编译但会引发核心段违规错误)。 我怎样才能做到这一点?

 uint8_t **NewMatrix(unsigned nrows, unsigned ncols) { uint8_t **matrix; size_t row_pointer_bytes = nrows * sizeof *matrix; size_t single_row_elements_bytes = ncols * sizeof **matrix; matrix = malloc(row_pointer_bytes + nrows * single_row_elements_bytes); unsigned i; for(i = 0; i < nrows; i++) matrix[i] = matrix[nrows + i * single_row_elements_bytes]; return matrix; } 

除了另一个答案中提到的各种错误之外,您正在错误地分配2D数组。 实际上你根本没有分配一个2D数组,而是一个缓慢的,零碎的查找表。

在如何正确设置,访问和释放C中的多维数组中描述了动态分配2D数组的正确方法? 。 有关如何工作以及数组指针如何工作的详细说明,请参见函数动态分配矩阵 。

以下是使用上述技术的示例,针对您的具体情况:

 #include  #include  #include  #include  void NewMatrix (size_t nrows, size_t ncols, uint8_t (**matrix)[nrows][ncols]) { *matrix = malloc ( sizeof (uint8_t[nrows][ncols]) ); } int main (void) { size_t r = 3; size_t c = 4; uint8_t (*arr_ptr)[r][c]; NewMatrix(r, c, &arr_ptr); uint8_t (*matrix)[c] = arr_ptr[0]; uint8_t count=0; for(size_t i=0; i 

我认为您的代码存在一些问题。

  • 您可以简化此行:

     matrix = malloc(row_pointer_bytes + nrows * single_row_elements_bytes); 

    至:

     matrix = malloc(row_pointer_bytes); 

    这为矩阵中的uint8_t*许多行分配空间。

    malloc()函数只需要在堆上分配请求的内存所需的size_t字节数,并返回指向它的指针。

    并且可以通过知道矩阵中需要多少行来简单地分配,在这种情况下为nrows

  • 另外,你的for循环:

     for(i = 0; i < nrows; i++) matrix[i] = matrix[nrows + i * single_row_elements_bytes]; 

    不为matrix[i]分配内存,因为每行有n列,并且您需要为这些列分配内存。

    这应该是:

     for(i = 0; i < nrows; i++) matrix[i] = malloc(single_row_elements_bytes); 
  • 另一个问题是如何分配single_row_elements_bytes 。 代替:

     size_t single_row_elements_bytes = ncols * sizeof **matrix; //**matrix is uint8_t** 

    这需要为n列分配uint8_t字节,而不是uint8_t**字节。 它可以是这样的:

     size_t single_row_elements_bytes = ncols * sizeof(uint8_t); 

话虽如此,如果这样编写,你的代码将编译。 这是我为测试代码而编写的一个例子。

 #include  #include  #include  #include  uint8_t **NewMatrix(unsigned nrows, unsigned ncols); int main(int argc, char *argv[]) { uint8_t **returnmatrix; unsigned nrows = 2, ncols = 2; int i, j; returnmatrix = NewMatrix(nrows, ncols); for (i = 0; i < nrows; i++) { for (j = 0; j < ncols; j++) { printf("Enter number for row %d column %d: ", i+1, j+1); /* format speficier for uint8_t, from  */ if (scanf("%"SCNu8"", &returnmatrix[i][j]) != 1) { printf("Invalid 8 bit number.\n"); exit(EXIT_FAILURE); } } } printf("\nYour matrix:\n"); for (i = 0; i < nrows; i++) { for (j = 0; j < ncols; j++) { printf("%d ", returnmatrix[i][j]); } printf("\n"); } /* Good to free at the end */ free(returnmatrix); return 0; } uint8_t **NewMatrix(unsigned nrows, unsigned ncols) { int i; uint8_t **matrix; size_t row_pointer_bytes = nrows * sizeof * matrix; size_t column_row_elements_bytes = ncols * sizeof(uint8_t); matrix = malloc(row_pointer_bytes); /* Good to check return value */ if (!matrix) { printf("Cannot allocate memory for %d rows.\n", nrows); exit(EXIT_FAILURE); } for(i = 0; i < nrows; i++) { matrix[i] = malloc(column_row_elements_bytes); if (!matrix[i]) { printf("Cannot allocate memory for %d columns.\n", ncols); exit(EXIT_FAILURE); } } return matrix; } 

输入:

 Enter number for row 1 column 1: 1 Enter number for row 1 column 2: 2 Enter number for row 2 column 1: 3 Enter number for row 2 column 2: 4 

输出:

 Your matrix: 1 2 3 4 

编译:

 gcc -Wall -o matrix matrix.c 
  for (i=0;i 

以下2行必须由上述2行代替

  for(i = 0; i < nrows; i++) matrix[i] = matrix[nrows + i * single_row_elements_bytes]; 

使用(nrows + i * single_row_elements_bytes)作为分配大小,并且使用nrows = 5ncols =5 ,例如,分配总共65个字节。 这包括40个字节来存储行指针(假设64位指针大小),其余25个字节来存储每个r,c元素的内容。 但是没有分配列指针的内存(指向该行中每个元素的指针)。

因此,解除引用matrix[i][j]将会出错。