Initialize a member of two dimensional dynamic struct - c

I am initializing a dynamic 2-dimensional struct in C like this:
typedef struct
{
int v;
unsigned int t;
} cb;
cb **b;
b = malloc( sizeof(*b) * s + (s * (e * sizeof(**b) )));
s and e are dimensions of the array(row and column size)
How do I also initialize b with v set as 0?

Never use pointer-to-pointer lookup tables for the purpose of dynamically allocating 2D arrays. It is widespread but bad and incorrect practice, leading to segmentation and slow programs.
Instead, use an array pointer and allocate a true 2D array in adjacent memory:
cb (*arr)[y] = malloc( sizeof(cb[x][y]) );
arr[i][j] = something;
free(arr);
To initialize everything to zero, use calloc instead of malloc. To initialize everything to a given value, you have to use a loop and assign values one by one.

Use calloc instead of using malloc.

Related

How to use double pointer as pointer arrays?

Version 1:
struct mydef_s1 {
int argc;
char *argv[3];
};
struct mydef_s1 *p1 = (struct mydef_s1*) malloc (sizeof (struct mydef_s1));
p1->argv[0] = malloc (8);
p1->argv[1] = malloc (16);
p1->argv[2] = malloc (24);
Now, I want to achieve above with the following structure declaration?
Version 2:
struct mydef_s2 {
int argc;
char **argv;
};
If I am right, then following would like allocate just 8 bytes (4 for memory pointer & 4 for integer in my machine)
struct mydef_s2 *p2 = (struct mydef_s2*) malloc (sizeof (struct mydef_s2));
What should I do to do the following?
p2->argv[0]= malloc(4);
p2->argv[1]=malloc(8);
In the case of a pointer to pointer like
struct mydef_s2 {
int argc;
char **argv;
};
you have to first allocate the memory for argv itself, then for argv[i]s.
Something like (code is without error check)
argv = malloc(n * sizeof*argv); //allocate memory to hold 'n' number of 'argv[i]'s
for (i = 0; i < n; i++)
argv[i] = malloc(32); //allocate individual `argv[i]`s
will do the job.
A pointer in C is behaving somewhat like an array. A pointer to pointer, however, is something completely different than a two dimensional array.
If you meant what you typed, i.e. - an array of a non (compiled time) known size of pointers to arrays of non compiled time known sizes of chars, then you will need to do just that. Allocate storage for the array of pointers, place that in your argv, and then initialize each position there with a pointer, possibly dynamically allocated with malloc, of the actual array of chars.
If, on the other hand, you meant a two dimensional array, you have two ways to proceed. One is to do the above, possibly saving a step by allocating the inner nesting in one malloc at one go. This is somewhat wasteful in memory.
The other option is to simulate what the compiler does for two dimensional arrays. Allocate n*m chars as a single dimension array, and jump into it by with the formula i = r*m + c, where r is the row index, m is the row size, and c is the column index.
While somewhat verbose, this is what C does when you define a two dimensional array. It is also quicker to allocate, initialize and use than the alternative.

How to change the size of a struct using malloc

I am making a struct with undefined size.
#define namemax 128
struct Image{
char name[namemax+1];
int length;
double *array; //double array[256]
};
struct Image* graph;
graph=malloc(max*sizeof(struct Image));
If I define array[256], everything work fine.
but if I use double *array, and then write
graph[check].array = malloc( 100 * sizeof(double *));
it creates a segment fault.
I was wondering how can I define the size using malloc and realloc for array.
If I add value in the array, it shows segment fault.
struct Image* graph;//outside the while loop
while: //it is inside the while loop
//basically it read different name each line, and put the x and y to the array
graph[check].array = malloc( 100 * sizeof(double));
check++;
strcpy( graph[check].name,type);
graph[check].array[count]=shiftX;
graph[check].array[count+1]=shiftY;
That because double * array is declaring a pointer to an array, not storage. You want to declare storage here. The easiest way is to simply define the array as double array[1] and make sure it's the last element in the struct. You can then allocate space for the structure using malloc() and realloc() by passing them the size of the base struct plus the size of the array (sizeof double * the number of array elements).
One problem I see is using sizeof(double *) instead of sizeof(double) even if both are the same if you're using x86-64 architecture.
i think it makes seg fault because in malloc you have said sizeof(double *) (Actually you declare an array of array).
Just try to say sizeof(double) it may work but I dont know that for sure because I haven't tested it.
And by the way when you declare array staticly you reserve space for it when you declare your struct variable but when you declare it as pointer ( dynamic array ) you should reserve space for it and you can change the array's size. You should use realloc google it.

Crash while re-organizing 1d buffer as 2d array

I have a 1d buffer which i have to re-organize to be accessed as a 2d array. I have pasted my code below:
#include <stdlib.h>
#include <stdio.h>
void alloc(int ** buf, int r, int c)
{
int **temp=buf;
for(int i=0; i<r; i++)
buf[i]=(int *)temp+i*c;
}
void main()
{
int *buffer=(int *)malloc(sizeof(int)*100);
int **p = (int**) buffer;
alloc(p, 4, 4);
//for(int i=0;i<r;i++)
//for(int j=0;j<c;j++)
// printf("\n %p",&p[i][j]);
p[0][3]=10;
p[2][3]=10;
p[3][2]=10; //fails here
printf("\n %d", p[2][3]);
}
The code is crashing when i make the assignment.
I have ran the code for different test cases. I have observed that the code crashes when there is an assignment to p[0][x] followed by assignment to p[x][anything] with the code crashing at the second assignment. This crash is seen only when the first index of the first assignment is 0 and for no other indices with the crash happening at the second assignment having the first index equal to the second index of the first assignment.
For example, in the above code crash happens at p[3][2] after p[0][3] has been executed. If i change the first assignment to p[0][2] then crash would happen at p[2][3]( or p[2][anything] for that matter).
I have checked the memory pointed to by p, by uncommenting the double for loop, and it seems to be fine. I was suspecting writing at illegal memory locations but that has been ruled out by the above observation.
The problem is that your 2D array is actually an array of pointers to arrays. That means you need to have space for the pointers. At the moment you have your pointers in positions 0-3 in the array, but p[0] is also pointing to position 0. When you write to 'p[0,3]' you are overwriting p[3].
One (tempting) way to fix it is to allow the pointers room at the start of the array. So you could change your alloc method to allow for some space at the front. Something like:
buf[i] = (int *)(temp+r) + i*c;
Note the +r adding to the temp. It needs to be added to temp before it is cast as you can't assume int and int * are the same type.
I would not recommend this method as you still have to remember to allocate extra space in your original malloc to account for the array of pointers. It also means you aren't just converting a 1D array to a 2D array.
Another option would be to allocate your array as an array of pointers to individually allocated arrays. This is the normal way to allocate 2D arrays. However this will not result in a contiguous array of data as you have in your 1D array.
Half way between these two options, you could allocate an extra array of pointers to hold the pointers you need, and then point them to the data. Change your alloc to something like:
int **alloc(int * buf, int r, int c)
{
int **temp = (int **)malloc(sizeof (int *)* r);
for (int i = 0; i<r; i++)
temp[i] = buf + i*c;
return temp;
}
then you call it like:
int **p = alloc(buffer, 4, 4);
you also need to free up the extra buffer.
This way your data and the pointers you need to access it are kept separate and you can keep your original 1D data contiguous.
Note that you don't need to cast the result of malloc in c, in fact some say that you shouldn't.
Also note that this method removes all of the requirement for casting pointers, anything that removes the need for a cast is a good thing.
I think that your fundamental problem is a misconception about 2D arrays in C (Your code is C, not C++).
A 2D array is a consecutive memory space , and the size of the inner array must be known in advance. So you basically cannot convert a 1D array into a 2D array unless the size of the inner array is known at compile time. If it is known, you can do something like
int *buffer=(int *)malloc(sizeof(int)*100);
typedef int FourInts[4];
FourInts *p = (FourInts *)buffer;
And you don't need an alloc function, the data is already aligned correctly.
If you don't know the size of the inner array in advance, you can define and allocate an array of arrays, pointing into the 1D buffer. Code for that:
int ** alloc(int * buf, int r, int c)
{
int **array2d = (int **) malloc(r*sizeof(int *));
for(int i=0; i<r; i++)
array2d[i] = buf+i*c;
return array2d;
}
void _tmain()
{
int *buffer=(int *)malloc(sizeof(int)*100);
int **p = alloc(buffer,4,4);
p[0][3]=10;
p[2][3]=10;
p[3][2]=10; //fails here
printf("\n %d", p[2][3]);
free(buffer);
free(p);
}
But it would have been easier to simply build an array of arrays without using the buffer. If you could use C++ instead of C, then everything could be easier.
If you already have a 1D block of data, the way to make it accessible as a 2D array is to create an array of pointers - one for each row. You point the first one to the start of the block, the next one is offset by the number of columns, etc.
int **b;
b = malloc(numrows*sizeof(int*));
b[0]=temp; // assuming temp is 1D block
for(int ii=1; ii<numrows;ii++)
b[ii]=b[0]+ii*numcols;
Now you can access b[i][j] and it will point to your original data. As long as number of rows and columns are known at run time this allows you to pass variable length 2D arrays around. Remember that you have to free the vector of pointers as well as the main data block when you are done or you will get a memory leak.
You will find examples of this if you google nrutil.c - this is derived from the trick Numerical Recipes in C uses.
This function prototype should be:
void alloc(int *buf[][], int r, int c) //buf[][] <=> **buf, but clearer in this case
{
//*(buf[i]) =
...
}
If you want to work on the same array you have to pass a pointer to this 2D array (*[][]).
The way you do it now is just working on a copy, so when you return it's not modified.
You should also initialize your array correctly :
p = malloc(sizeof(int *[]) * nb of row);
for each row
p[row] = malloc(sizeof(int []) * nb of col);

Declaring and Initializing 2D array of unknown size in C

I plan to create an 2D array of a pointer derived from typedef struct
Let's say the typedef struct is named "Items" and contains mixed variables of strings and integers.
I will declare two intvariables namely typenum and typetotal. These two integers will start off from Zero and adds up when the input data matches with certain function.
In the array,Items *type[][], basically type[][] is Items *type[typenum][typetotal] but I cannot do this since I will declare typenum and typetotal as zero at the declaration part.
I tried initializing the array through Items *type[][] = {{0},{0}} but this generates error.
Any advice? Some told me to use malloc() on this, but I simply do not know how.
*Using Tiny C on Windows
Use dynamic memory allocation.
Items **type;
type = malloc(sizeof (Items *) * typenum);
for (int i = 0; i < typenum; i++)
type[i] = malloc(sizeof Items) * typetotal);
You need to manually free the allocated memory after using the array.
for (int i = 0; i < typenum; i++)
free(types[i]);
free(types);
Here is a tutorial on it: http://www.eskimo.com/~scs/cclass/int/sx9b.html
If typenum and typetotal increase as your program runs be sure to use realloc, which will reallocate more memory and keep the contents. You'll need to allocate the first dimension of the array like this:
myArray = realloc(myArray, sizeof(Items*) * typenum);
and then allocate the second dimension for each of the first:
for(...)
myArray[i] = realloc(myArray[i], sizeof(Items) * typetotal);

Deep copying array in C... malloc?

I'm trying to make a deep copy of an array in C (originalBoard being the copy):
int gy, gx;
for (gy=0; gy<9; gy++)
{
for (gx=0; gx<9; gx++)
{
g.originalBoard[gy][gx]=g.board[gy][gx];
}
}
This does not seem to be working out, and I'm guessing this is just making pointers to the original board array.
So would the solution be to try and use malloc? Like:
int* g.originalBoard[9][9]=malloc(sizeof(g.board[9][9]));
btw this is a 9x9 two dimensional array. What would the syntax be (the compiler gives an error for the above line...)?
I think you need this:
//assuming g.originalBoard is array of array of integers and same for g.board
int *originalBoard = malloc(sizeof(g.board));
memcpy(originalBoard, g.board, sizeof(g.board));
This is the correct place to use memcpy. You probably want
g.originalBoard = (int *)malloc(9 * 9 * sizeof(int));
if (NULL == g.originalBoard) {
/* malloc failed, so handle the error somehow */
}
memcpy(g.originalBoard, g.board, 9 * 9 * sizeof(int));
You may notice that in the above solution you have to use g.board[r * 9 + c] to access the item at index (r, c), rather than two indices. This is because of the way this dynamically allocates memory - at compile-time g.board and g.originalBoard are just pointers, not arrays. Alternatively, if you have control over the definition of the type of g, you can hardcode the size of the matrix as
struct foo {
int board[9][9];
int originalBoard[9][9];
/* Other fields here */
};
Then you wouldn't have to malloc extra space for g.board and g.originalBoard - those two fields would be automatically allocated whenever you allocated space for g itself. Also, you could use g.board[r][c] instead of g.board[r * 9 + c].
By the way, if you are trying to execute the following 'intended' task on the arrays,
int* g.originalBoard[9][9]=malloc(sizeof(g.board[9][9]));
then you should change the above line to
int* g.originalBoard[8][8]=malloc(sizeof(g.board[8][8]));
because this is a 9x9 two dimensional array and in C arrays are ZERO-based.

Resources