在动态矩阵上设置指针
我正在尝试制作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 = 5
和ncols =5
,例如,分配总共65个字节。 这包括40个字节来存储行指针(假设64位指针大小),其余25个字节来存储每个r,c元素的内容。 但是没有分配列指针的内存(指向该行中每个元素的指针)。
因此,解除引用matrix[i][j]
将会出错。