 # Set pointers on Dynamic Matrix

I'm trying to make a dynamic size matrix of 1-byte elements. To do so I defined the following function. The problem comes when I try to set the first "nrows" elements of the matrix to point the corresponding row (so I can do matrix[i][j]). It looks like that `matrix[i] = matrix[nrows + i * single_row_elements_bytes];` doesn't work well enough (the program compiles but throws an core-segment-violation error). How can I make this work?

```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; } ```

Apart from various bugs mentioned in another answer, you are allocating the 2D array incorrectly. You are actually not allocating a 2D array at all, but instead a slow, fragmented look-up table.

The correct way to allocate a 2D array dynamically is described at How do I correctly set up, access, and free a multidimensional array in C?. Detailed explanation about how this works and how array pointers work is explained at Function to dynamically allocate matrix.

Here is an example using the above described techniques, for your specific case:

```#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; 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); } ```

I think there are a couple of problems with your code.

<li>

You can simplify this line:

```matrix = malloc(row_pointer_bytes + nrows * single_row_elements_bytes); ```

to:

```matrix = malloc(row_pointer_bytes); ```

Which allocates space for `uint8_t*` many rows in the matrix.

The `malloc()` function only requires `size_t` amount of bytes needed to allocate requested memory on the heap, and returns a pointer to it.

and that can simply be allocated by knowing how many rows are needed in the matrix, in this case `nrows`.

</li> <li>

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

Doesn't allocate memory for `matrix[i]`, since each row has `n` columns, and you need to allocate memory for those columns.

This should instead be:

```for(i = 0; i < nrows; i++) matrix[i] = malloc(single_row_elements_bytes); ```</li> <li>

Another issue is how are allocating `single_row_elements_bytes`. Instead of:

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

This needs allocate `uint8_t` bytes for `n` columns, not `uint8_t**` bytes. It can be this instead:

```size_t single_row_elements_bytes = ncols * sizeof(uint8_t); ```</li> </ul>

Having said this, your code will compile if written like this. This is an example I wrote to test the code.

```#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; } ```

Input:

```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 ```

Output:

```Your matrix: 1 2 3 4 ```

Compiled with:

```gcc -Wall -o matrix matrix.c ```

``` for (i=0;i<nrows;i++) matrix[i] = (uint8_t *)malloc(ncols * sizeof(uint8_t)); ```

The below 2 lines have to be replaced by the above 2 lines

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

with `(nrows + i * single_row_elements_bytes)` as the allocation size, and with `nrows = 5` and `ncols =5`, say, a total of 65 bytes are allocated. This include 40 bytes to store row pointers(assuming a 64bit pointer size) and rest 25 bytes to store contents of each r,c element. But the memory for column pointer (pointer to each element in that row) is not allocated.

So, dereferencing `matrix[i][j]` will seg fault.

 人点赞