我正在尝试制作1字节元素的动态大小矩阵。为此,我定义了以下功能。当我尝试设置矩阵的第一个" 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 <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <inttypes.h>
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<r; i++)
{
for(size_t j=0; j<c; j++)
{
matrix[i][j] = count;
count++;
printf("%2."PRIu8" ", matrix[i][j]);
}
printf("n");
}
free(arr_ptr);
}
我认为您的代码有两个问题。
-
您可以简化此行:
matrix = malloc(row_pointer_bytes + nrows * single_row_elements_bytes);
to:
matrix = malloc(row_pointer_bytes);
在矩阵中为
uint8_t*
分配空间。malloc()
函数仅需要size_t
在堆上分配请求的内存所需的字节数量,并返回指针。可以简单地通过知道矩阵中需要多少行来分配,在这种情况下为
nrows
。 -
此外,您的循环:
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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
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 <inttypes.h> */
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<nrows;i++)
matrix[i] = (uint8_t *)malloc(ncols * sizeof(uint8_t));
以下2行必须用以上2行替换
for(i = 0; i < nrows; i++)
matrix[i] = matrix[nrows + i * single_row_elements_bytes];
以(nrows + i * single_row_elements_bytes)
为分配大小,并且nrows = 5
和ncols =5
(例如,总共分配了65个字节。其中包括40个字节来存储行指针(假设有64位指针尺寸)和REST 25个字节存储每个R,C元素的内容。但是,未分配列指针的内存(指向该行中的每个元素的指针)。
所以,删除matrix[i][j]
将出现故障。