How to use double pointer as pointer arrays? - c

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.

Related

Different arrays in dynamic struct, creation, writting, reading

Strait to the point.
I have a struct with a string, char and int.
The struct is created dynamically because i will need it in different parts of my program.
struct A
{
char staticString[20];
char* dynamicString;
char character;
int integer;
};
I know if i want to create a struct i call:
A example = (A)malloc(sizeof(A));
In order to populate the dynamicString and int i used:
example->dynamicString = (char*)malloc(sizeof(char*));
example->integer = (int)malloc(sizeof(int));
Unfourtanetly when i tried to populate staticString and char it didn't worked.
Don't even ask what was my code for those, i tried a lot of combinations from everywhere.
In addition to that can somebody show me examples how to write/read those values?
Thanks in advance.
First things first:
You're using C, and by the way you've defined the structure, you need to declare the pointer like so:
struct A *example;
Next, malloc returns a pointer, so you need to cast to a pointer (and not to a structure):
(struct A *)malloc(sizeof(struct A));
Secondly, I'm not sure why but hey:
- you're trying to dynamically allocate an int in the structure. As I said previously, malloc returns a pointer, so in your structure you need an int pointer like so "int *integer;"
- you're trying to allocate a dynamic string, however you're not doing it properly, here is what I think you want
example->dynamicString = (char *)malloc(sizeof(char) * 10);
Where 10 is the size of your dynamic string.
Edit:
you may also populate the integer in your struct statically or dynamically, but I think you intended the static approach:
example->integer = 123;
The dynamic approach would be (assuming you have int *integer in your struct):
example->integer = (int *)malloc(sizeof(int));
*(example->integer) = 123;
Every time you create a new struct the memory in the heap is set to size of :
sizeof(char)*20 + sizeof(char pointer) +sizeof(char)+ sizeof(int).
If you want to save a string that will be pointed to by your char pointer- then you ask for allocation in heap for the size of that string- and malloc returns the pointer to that memory allocation on heap.
So, you already have a space for your char array, char pointer, char and int that was allocated when you asked to make a new struct and do not need to allocate it again.
also, keep in mind malloc returns a pointer to the allocated place on the heap- so if you malloc(sizeof(int)) you get a pointer to a memory allocation for an int on the heap- which is pointed to by a int pointer Not an int.
good luck!

How do you use malloc to allocate space for an array of structures?

I'm currently working on dynamically allocating my array of structures and I'm unsure how to continue. This is my structure:
struct Word_setup
{
char word[M];
int count;
} phrase[N];
I know malloc returns a pointer to a block of memory, but I'm not sure how this works when it comes to an array of structures.
If anyone could please clarify that would be much appreciated!
Probably you meant:
struct Word_setup {
char word[M];
int count;
};
It's a good idea to avoid defining variables in the same line as a struct definition anyway, to help with code readability.
Then you can allocate an array of these:
int main()
{
struct Word_setup *phrase = malloc(N * sizeof *phrase);
// use phrases[x] where 0 <= x < N
phrase = realloc(phrase, (N+5) * sizeof *phrase);
// now can go up to phrases[N+4]
free(phrase);
}
Of course you should check for failure and abort the program if malloc or realloc returns NULL.
If you also want to dynamically allocate each string inside the word then there are a few options; the simplest one to understand is to change char word[M] to char *word; and each time you allocate a phrase, write the_phrase.word = malloc(some_number); . If you allocate an array of words you'll need to loop through doing that for each word.
I suppose that N and M is a compile-time known constants. Then just use sizeof, .e.g.
struct Word_setup*ptr = malloc(sizeof(struct Word_setup)*N);
Maybe you want a flexible array member. Then, it should always be the last member of your struct, e.g.
struct Word_setup {
int count;
unsigned size;
char word[]; // of size+1 dimension
};
Of course it is meaningless to have an array of flexibly sized structures -you need an array of pointers to them.

Memory leak in C

I am using GTK, and I am not sure with malloc() function here. Valgrind gives me a memory leak, what I am doing bad?
at first I create pointer to pointer to pointer to GTK widget, because I need three dimensional array.
GtkWidget*** widgets;
and I am using malloc like this:
widgets = malloc((1)*sizeof(GtkWidget**));
for(i = 0; i<= l-1; i++) // l = 4 in my case
{
widgets[i] = malloc((1)*sizeof(GtkWidget*));
for(j = 0; j<=3; j++) // 4 is number of elements in this dimension
{
widgets[i][j] = malloc((1)*sizeof(GtkWidget));
}
}
and at the end I am doing this:
widgets[0][0] = gtk_menu_item_new_with_label("MyLabel");
gtk_menu_shell_append(GTK_MENU_SHELL(indicator_menu), widgets[0][0]);
my array can be smaller and bigger, so I am using dynamic allocation of array, my maximal array indexes are something like widgets[3][3].
I did not post whole code, because it is pretty long, I sent here just the parts for which was valgrind complaining to. What I am doing bad? thank you.
You're only allocating the size of a pointer, when you mean to allocate an array of pointers.
// this will allocate a single character pointer
char ** ptr = malloc(1 * sizeof(char *));
// this will allocate n character pointers
char ** ptr = malloc(n * sizeof(char *));
So if you want a two dimensional array of dimension NxM, you'll need to allocate an array of size N, then walk through that array from 0 to N-1 and allocate arrays of size M.
What you're doing now is assigning pointers returned from malloc to memory you don't own. Is what you actually want a two-dimensional array of pointers to GtkWidget structures?
Using l as a local variable is not a good idea. It is very easy to make a mistake between l and 1, in some editors they look very much the same.
widgets = malloc((l)*sizeof(GtkWidget**)); //is what you needed
iso
widgets = malloc((1)*sizeof(GtkWidget**));
Over here with syntax highlighting the problem immediately appears.
So another suggestion is to for sure use an editor with syntax highlighting

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);

Handling an array of pointers

I'm attempting to create a struct that has an array of char pointers as one of its members and am having trouble attempting to set/access elements of the array. Each char pointer is going to point to a malloc'd buffer. This is the struct currently.
struct rt_args {
long threadId;
char (*buffers)[];
FILE* threadFP;
};
And when I attempt to access an element of buffers via
char *buffer = malloc(100);
struct rt_args (*rThreadArgs) = malloc( sizeof(long) +
(sizeof(char *) * (numThreads)) +
sizeof(FILE*)
);
rThreadArgs->buffers[0] = buffer;
I get the error "invalid use of array with unspecified bounds". I don't know what the size of the array is going to be beforehand, so I can't hardcode its size. (I've tried de-referencing buffers[0] and and adding a second index? I feel as though its a syntactical error I'm making)
You can't have arrays without a size, just like the error message says, at least not n the middle of structures. In your case you might think about pointers to pointers to char? Then you can use e.g. malloc for the initial array and realloc when needed.
Something like
char **buffers;
Then do
buffers = malloc(sizeof(buffers[0]) * number_of_pointers_needed);
Then you can use buffers like a "normal" array of pointers:
buffers[0] = malloc(length_of_string + 1);
strcpy(buffers[0], some_string);
char (*buffers)[SIZE];
declares buffers as a pointer to char array not the array of pointers. I think you need this
char *buffers[SIZE];
NOTE: Flexible array member can be used only when it is the last member of the structure.

Resources