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;
}
}
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'm trying to make a code which converts some decimal numbers to bits.
There are more simple ways to reach this result but I'm poking around and joking with memory in C.
int ** decimalToBits(int *number,int size){
int **bits = (int **)malloc(sizeof(*bits)*size), i = 0;
for (int j = 0; j < size; j++) {
int * temp = (int *)malloc(sizeof(int));
while (number[j] >= 1) {
temp[i++] = number[j] % 2;
number[j] /= 2;
realloc(temp, sizeof(int));
}
printf("\n");
bits[j] = (int *) malloc(sizeof(int)*i);
for (int k = i-1; k >= 0; k--){
bits[j][k] = temp[k];
printf("%d" ,bits[j][k]);
}
i = 0;
}
return bits;
}
I'm having some allocation problems, first of all I'm going to explain the idea:
I pass to the function multiple numbers, so for example:
int numbers[2] = {23,73};
decimalToBits(numbers,2);
Each converted number will be stored in **bits double pointer, so bits[0] will contain the number 23 converted, and bits[1] will contain 73 converted as well.
The problem shows up when I do bits[j] = (int *) malloc(sizeof(int)*i); call,
because this seems to let the temp pointer to be overwritten with some random numbers. In fact if I remove the bits[j] = (int *) malloc(sizeof(int)*i); and bits[j][k] = temp[k]; lines and I replace printf("%d" ,bits[j][k]); with printf("%d" ,temp[k]);
the code seems to have a good behavior, and it gives me the correct output:
10111
1001001
I also noticed that allocating the bits[j] = (int *) malloc(sizeof(int)*8); externally from the for (int j = 0; j < size; j++) loop let the code works. So why this allocation problem occurs when declared just like the above code and what's the best way to solve it?
I am a bit of a beginner in C language. I was trying out a task of dynamically reallocating memory as the input comes through(although for this test I am doing a normal task, later will try to scale it up). the issue I am facing is I am unable to access the memory while writing into it. Can anyone please help me understand where I am going wrong in this code. thanks in advance.
code:
#include<stdio.h>
#include<stdlib.h>
struct ai {
int* a;
char* b;
};
int main()
{
struct ai *test;
test = (struct ai*) malloc(sizeof(struct ai));
test[0].a = (int*)malloc(sizeof(int));
test[0].b = (char*)malloc(sizeof(char));
/// storing info
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
test[i].a[j] = j;
test[i].b[j] = 65 + j;
test[i].a = (int *) realloc(test[i].a, (j + 2) * sizeof(int));
test[i].b = (char*) realloc(test[i].b, (j + 2) * sizeof(char));
}
test = (struct ai*)realloc(test, (i + 2) * sizeof(struct ai));
}
// printing the block out
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d , %c\n", test[i].a[j], test[i].b[j]);
}
}
return 0;
} ```
You have missing initialization of your pointers and some other issues...
int main()
{
struct ai *test;
test = (struct ai*) malloc(sizeof(struct ai));
test[0].a = (int*)malloc(sizeof(int));
test[0].b = (char*)malloc(sizeof(char));
In C you should not cast the result of malloc. In best case it is useless. In worst case it hides real problems.
/// storing info
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
test[i].a[j] = j;
test[i].b[j] = 65 + j;
Here comes the reason for your segmentation fault:
You do not have any memory reserved for a and b except for the first element test[0]. All other array elements test[i] do not contain any useful data. Dereferencing these pointers is undefined behaviour.
You must allocate memory for each field after you enlarged your array.
test[i].a = (int *) realloc(test[i].a, (j + 2) * sizeof(int));
test[i].b = (char*) realloc(test[i].b, (j + 2) * sizeof(char));
You should never assign the return value of realloc to the same variable that you passed into the function. In case of an error you will get NULL return value and then your initiali pointer is lost.
Also here: don't cast for realloc as well.
}
test = (struct ai*)realloc(test, (i + 2) * sizeof(struct ai));
Same here: Don't assign to same variable and don't cast the result of realloc.
Finally: Here goes the missing part:
test[i+1].a = malloc(sizeof(*test[0].a));
test[i+1].b = malloc(sizeof(*test[0].b));
}
Of course you should check all return values for error results.
Not related to the segmentation fault, but still worth to fix:
You increment the size of each array after you used the last element.
This prepares the new element for being filled in next iteration of the loops. But in case of the last iteration it allocated an unused element for both the intern pointers a and b as well as the outer array test.
You will have some unused elements:
test[0].a[4]
test[0].b[4]
test[1].a[4]
test[1].b[4]
test[2].a[0]
test[2].b[0]
An improved solution could look like this (not tested)
I start with each pointer being NULL and use realloc right before the new element is used to avoid the extra elements.
int main(void)
{
struct ai *test = NULL
void *tmp;
// storing info
for (int i = 0; i < 2; i++)
{
tmp = realloc(test, (i+1) * sizeof(*test))
if (tmp == NULL)
exit(1);
test = tmp;
test[i].a = NULL;
test[i].b = NULL;
for (int j = 0; j < 4; j++)
{
tmp = realloc(test[i].a, (j+1) * sizeof(test[i].a[0]));
if (tmp == NULL)
exit(1);
test[i].a = tmp;
tmp = realloc(test[i].b, (j+1) * sizeof(test[i].b[0]));
if (tmp == NULL)
exit(1);
test[i].b = tmp;
test[i].a[j] = j;
test[i].b[j] = 65 + j;
}
}
// printing the block out
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d , %c\n", test[i].a[j], test[i].b[j]);
}
}
return 0;
}
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 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;
}