I have a two-dimensional int array allocated as follows:
int **matrix = (int**)malloc(x * sizeof(int));
for (i = 0; i < x; i++)
matrix[i] = (int*)malloc(y * sizeof(int));
If I do realloc this array by the following code
int **matrix = (int**)realloc(matrix, x * sizeof(int));
for (i = 0; i < x; i++)
matrix[i] = (int*)malloc((y) * sizeof(int));
will there be any leftover "tails" of second dimension of the array and should I use free() function for them before reallocating, or they will go away themselves?
You will completely lose data in your matrix, so this is not really reallocing anything; you could just as well free and malloc the top-level array, getting possibly better performance. Furthermore your code would leak memory, because the 2nd level allocations are not freed.
Here is how you can resize the 2D matrix while keeping the current values intact, initializing the newly allocated cells to 0 and freeing any extra leftovers:
// matrix was allocated to x and y
// reallocate it to newx, newy
for (i = newx; i < x; i++) { /* free unneeded rows */
free(matrix[i]);
}
matrix = realloc(matrix, sizeof(*matrix) * newx);
for (i = x; i < newx; i++) { /* initialize the new row pointers */
matrix[i] = NULL;
}
for (i = 0; i < newx; i++) {
matrix[i] = realloc(matrix[i], sizeof(*matrix[i]) * newy);
for (int j = y; j < newy; j++)
matrix[i][j] = 0;
}
Related
Why does this show a warning for dereferencing nullptr in C
Level1Tilemap->Map = (int*)((malloc(Level1Columns * sizeof(int))));
for (int i = 0; i < Level1Columns; i++)
{
Level1Tilemap->Map[i] = malloc(Level1Rows * sizeof(int));
for (int j = 0; j < Level1Rows; j++)
{
Level1Tilemap->Map[i][j] = Level1MapStaticArray[i][j];
}
}
I am using malloc to create a 2D array of ints
But the editor shows warning and Level1Tilemap->Map has the memory address of nullptr
And the defination int** Map;
You might have meant to use a pointer-to-pointer, in which case sizeof(int) should have been sizeof(int*). However, don't do that, it's obscure and slow, for no good reason.
Instead do
size_t size = sizeof(int[Level1Columns][Level1Rows]);
int (*something)[Level1Rows] = malloc(size);
if(something == NULL) { /* error handling */ }
memcpy(something, Level1MapStaticArray, size);
...
free(something);
Apart from reducing code complexity, this will significantly outperform the code you have currently.
// map is an array of (int*), and the length is column
int** map = (int**) malloc(column * sizeof(int*));
for (int i = 0; i < column; ++i) {
// map[i] is an array of int, and the length is row
map[i] = malloc(row * sizeof(int*));
for (int j = 0; j < row; ++j)
map[i][j] = 0;
}
I have a 2 dimensional array of pointers:
typedef struct Cell{
Position p;
unsigned int value;
} Cell;
typedef struct Position{
unsigned int x;
unsigned int y;
} Position;
int size = 4;
Cell ***cells = malloc(sizeof(Cell**) * size);
int i,j;
for(i = 0; i < size; i++){
cells[i] = malloc(sizeof(Cell*) * size);
for(j = 0; j < size; j++){
cells[i][j] = malloc(sizeof(Cell));
}
}
What I want to do now is fill this array with pointers to cells, and initialize these cells to contain the value 0 like this:
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
Position p = {i,j};
Cell c = {p, 0};
cells[i][j] = &c; //This doesn't work
}
}
As you can already tell, writing the address of c into the pointer cells[i][j] is less than ideal, since every pointer now points to the same address. However I don't know how to fill this array with pointers pointing to individual addresses.
I tried something like this:
cells[i][j]->value = 0;
which of course also doesn't work. Can anyone give me a hint on how I can solve my problem?
I'm not sure why you say cells[i][j]->value = 0; doesn't work, I believe it should.
This should work to set all the members.
Cell ***cells = malloc(sizeof(Cell**) * size);
for(i = 0; i < size; i++){
cells[i] = malloc(sizeof(Cell*) * size);
for(j = 0; j < size; j++){
cells[i][j] = malloc(sizeof(Cell));
cells[i][j]->p.x = i;
cells[i][j]->p.y = j;
cells[i][j]->value = 0;
}
}
Additional:
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
Position p = {i,j};
Cell c = {p, 0};
cells[i][j] = &c; //This doesn't work
}
// to this line, 'c' & 'p' will be freed since it was allocated on stack not heap.
// 'c' & 'p' will be freed when program gets out of 2nd for loop, so either you can
// use memcpy to copy 'c' into cells[i][j] or use malloc to allocate 'c' and 'p'
}
You've already gotten your answer but I see no obvious reason to do that many allocations unless sizeof(Cell) * size * size is large enough to make a single allocation fail (but allocating smaller parts doesn't). I suggest doing one allocation only which gives a few benefits. In no particular order:
Faster allocation in most cases.
Faster access to the elements that will be tightly packed and therefore be more cache friendly.
Easier memory management - there is only one pointer to check and free.
Less total memory allocated than when allocating memory for a lot of pointers.
Example 1 - Make cells a pointer to the first of size number of elements of Cell[size].
// one allocation:
Cell (*cells)[size] = malloc( size * sizeof *cells );
if(cells == NULL) exit(1); // check for allocation failure
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
cells[i][j].p.y = i;
cells[i][j].p.x = j;
cells[i][j].value = 0;
}
}
Example 2 - Make cells a pointer to a single Cell[size][size]:
// one allocation:
Cell (*cells)[size][size] = malloc( sizeof *cells );
if(cells == NULL) exit(1); // check for allocation failure
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
(*cells)[i][j].p.y = i;
(*cells)[i][j].p.x = j;
(*cells)[i][j].value = 0;
}
}
I'm trying to multiply two dynamic matrices by passing them through a function. I'm getting a segmentation fault during the multiplication.
The matrices are being passed through a function. The items in the arguments are correct because I had to use them for a different operation in this project. I have a feeling that I messed up with the pointers, but i'm pretty new to C and i'm not sure where I messed up.
double** multiplyMatrices(
double** a,
const uint32_t a_rows,
const uint32_t a_cols,
double** b,
const uint32_t b_cols){
uint32_t i = 0;
uint32_t j = 0;
uint32_t k = 0;
double** c;
//allocate memory to matrix c
c = (double **)malloc(sizeof(double *) * a_rows);
for (i = 0; i < a_rows; i++) {
*(c +i) = (double *)malloc(sizeof(double) * b_cols);
}
//clear matrix c
for(i = 0; i < a_rows; i++){
for(j = 0; j < a_cols; j++){
*c[j] = 0;
}
}
i = 0;
//multiplication
while(j = 0, i < a_rows ){
while(k = 0, j < b_cols){
while(k < a_cols){
//following line is where i'm getting the segmentation fault
*(*(c+(i*b_cols))+j) += (*(*(a+(i*a_cols))+k)) * (*(*(b+(k*b_cols))+j));
k++;
}
j++;
}
i++;
}
return c;
}
The obvious mistake is that you dereference c + i * b_cols while c is an array of pointers of size a_rows. So likely c + i * b_cols is outside of the area that you previously allocated with malloc().
I would suggest to simplify the matrix representation using a single array of double with the size equal to the total number of elements, i.e. rows * cols.
For example:
double *c;
c = malloc(sizeof(double) * a_rows * b_cols);
This not only has better overall performance, but simplifies the code. You would then have to "linearise" the offset inside your unidimensional array to convert from bi-dimensional matrix coordinates. For example:
c[i * b_cols + j] = ...
Of course, the other two matrices need to be allocated, filled and accessed in a similar manner.
For code clarity, I would also replace the while statements by for statements with the actual variable that they loop on. For example:
for (i = 0; i < a_rows; i++)
for (j = 0; j < b_cols; j++)
for (k = 0; k < a_cols; k++)
You can (ab)use the C language in many ways, but the trick is to make it more clear for you in the first place.
This code should multiply matrix A with matrix B and calculate matrix C.
matA 3x2, matB 2x3 therefore matC should be `3x3.
However, when I print matC, the 3rd row contains garbage values.
I don't know where the mistake is — if I do something wrong with the pointers or maybe the calculate part is wrong.
This is what I see when printing it.
x x 2489458943
x x 2489587641
x x 2489745734
Or something like that.
I don't know why sometimes it works.
I mean it prints the correct values, but most of the time this is what I see.
#include <stdio.h>
int main() {
int x = 0,y = 0, z = 0;
int i,j,k;
int **matA;
int **matB;
int **matC;
matA = (int**)malloc(sizeof(int)*3); // making the matrixes by malloc functions
matB = (int**)malloc(sizeof(int)*2);
matC = (int**)malloc(sizeof(int)*3);
for(i = 0; i < 3; i ++)
{
matA[i] = (int*)malloc(sizeof(int)*2); // matA 3x2
}
for(i = 0; i < 2; i++)
{
matB[i] = (int*)malloc(sizeof(int)*3); // matB 2x3
}
for(i = 0; i < 3; i++)
{
matC[i] = (int*)malloc(sizeof(int)*3); // the calculated mat 3x3
}
for(i = 0; i < 3; i++)
{
printf("please eneter line number: %i",i+1); //putting the values by scanf function in matA
printf(" seperated with ','\n");
scanf("%d,%d",&x,&y);
matA[i][0] = x;
matA[i][1] = y;
}
for(i = 0; i < 2; i++)
{
printf("please eneter line number: %i",i+1);// putting the values in matB
printf(" of the second mat seperated with ','");
scanf("%i,%i,%i", &x, &y, &z);
matB[i][0] = x;
matB[i][1] = y;
matB[i][2] = z;
}
for(i = 0; i < 3; i++) // multiple the matrixes by 3 loops
{
for(j = 0; j < 3; j++)
{
for(k = 0; k < 2; k++)
{
matC[j][i] += matA[j][k]*matB[k][i];
}
}
}
for(i = 0; i < 3; i ++)// just printing to check if the matrix correct
{
for(j = 0; j < 3; j++)
{
printf("%i ",(int**)matC[i][j]);
}
printf("\n");
}
return 0;
}
You're not allocating enough space in your matrixes:
matA = (int**)malloc(sizeof(int)*3);
matB = (int**)malloc(sizeof(int)*2);
matC = (int**)malloc(sizeof(int)*3);
You're allocating space for an array int but you need an array of int *. Most likely, pointers are larger than integers on your system which means your arrays aren't large enough to hold what you want and you run of the end of the array. Doing so invokes undefined behavior.
Allocate space for arrays of int *. Also, don't cast the return value of malloc:
matA = malloc(sizeof(int *)*3);
matB = malloc(sizeof(int *)*2);
matC = malloc(sizeof(int *)*3);
You're also adding to elements of matC without initializing them. You should set them to 0 before doing so:
matC[j][i] = 0;
for(k = 0; k < 2; k++)
{
matC[j][i] += matA[j][k]*matB[k][i];
}
You also don't need a cast here:
printf("%i ",(int**)matC[i][j]);
Since each matC[i][j] has type int and you're printing an int. This also invokes undefined behavior because the type of the expression doesn't match the type for the format specifier.
You never initialize matC and then use matC +=
The malloc function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. Try calloc instead.
Also, you have wrong int** initialization, should allocate pointer size sizeof(int*), not just sizeof(int):
matA = (int**)calloc(3, sizeof(int*));
matB = (int**)calloc(2, sizeof(int*));
matC = (int**)calloc(3, sizeof(int*));
I am currently implementing an N x 2 matrix of floats on the heap as follows:
float **matrix = malloc(sizeof(float*) * n_cols);
for (int i = 0; i < n_cols; ++i) {
matrix[i] = malloc(sizeof(float) * 2);
}
The elements of matrix are not contiguous in memory, making this data structure cache unfriendly (as I understand it). I am trying to re-write the above to create a genuine 2D array on the heap. Based on some previous SO posts, I tried the following:
float (*matrix)[2] = malloc(sizeof(float) * n_cols * 2);
However, this lead to a segmentation fault when I ran my code.
If you want the whole array to be contiguous then you need to declare it as follows.
float *matrix = malloc(n1 * n2 * sizeof(float));
Does this help. Note the second way the matrix has been allocated.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
size_t r = 0;
size_t c = 0;
int rows = 82;
int columns = 30;
float *matrix = malloc(rows * columns * sizeof(float));
for(r = 0; r < rows; r++) {
printf("%zu - ", r);
for(c = 0; c < columns; c++) {
printf("%zu|", c);
matrix[r + r*c] = 1.0;
}
printf("\n");
}
float **matrix2 = malloc(rows * sizeof(float*));
for(r = 0; r < rows; r++) {
matrix2[r] = malloc(columns * sizeof(float));
}
for(r = 0; r < rows; r++) {
printf("%zu - ", r);
for(c = 0; c < columns; c++) {
printf("%zu|", c);
matrix2[r][c] = 1.0;
}
printf("\n");
}
free(matrix);
for(r = 0; r < rows; r++) {
free(matrix2[r]);
}
free(matrix2);
return 0;
}
You can find a benchmark with the code here...
https://github.com/harryjackson/doc/blob/master/c/cache_locality_2d_array_test.c
I think you want something like this.
float ** matrix = malloc(sizeof(float) * ((n_col * 2) + (n_col * sizeof(float*));
for(i = 0; i < n_col; i++)
{
matrix[i] = matrix + (n_col *sizeof(float*)) + ((i * 2) *sizeof(float));
}
The size of your matrix is 2* n_col, however the first index into your matrix is going to be a pointer to a column. You have to allocate additional space for these pointers. This is where the (n_col * sizeof(float *)) comes into play. Each row is of size (2 * sizeof(float)), so each of the first indexed in the matrix need to point to an array of memory (2 * sizeof(float)) bytes away from the last one.
It looks something like this.
m[0] m[1] m[2]
matrix matrix + 1 * (2 * sizeof(float)) matrix + 2 * (2 * sizeof(float))
The second index deference a location into the memory pointed to by m[x].