In C, how do I allocate space for my struct? - c

I built a function that I'm trying to use to dynamically allocate memory for my struct like so. Just can't seem to get it to work
typedef struct My_Struct
{
char **array
}MyStruct
MyStruct * createMyStruct(int length)
{
MyStruct->array = malloc(sizeof(char *) * (length + 1));
}
int main(void)
{
MyStruct *new1 = createMyStruct(10);
return 0;
}

It's simple as allocating sizeof(MyStruct) and casting to MyStruct ptr:
MyStruct * createMyStruct(int length)
{
MyStruct* s = malloc(sizeof(MyStruct));
s->array = malloc(sizeof(char*) * (length + 1));
return s;
}
By the way, usually a struct doesn't have any pointers in it, but only arrays with fixed sizes or at least a char*[] instead of a char* since structs usually have a fixed size to be easier allocable.
If you use my above code don't forget to allocate the char*s the char** refers too since the malloc in my code only allocates the pointers and not the strings itselfes

You could not use MyStruct type to initialize its fields, since they are not static. You have to create struct instance first, initialize it and then - return from your method.
MyStruct * createMyStruct(int length)
{
MyStruct* pResult = malloc(sizeof(MyStruct));
pResult->array = malloc(sizeof(char *) * (length + 1));
return(pResult);
}
Do not forget to free memory after you finish to use it.
PS:
This code is also strange:
pResult->array = malloc(sizeof(char *) * (length + 1));
If you are trying to initialize array of strings of the same length, it is incorrect. You will get an array of length+1, containing uninitialized pointers. If you are simply allocating an array to use its later - then incrementing length is possibly wrong.

Related

Problem with setting the array of pointers in the struct using malloc

I want to allocate a memory to an array of pointers in struct, but I receive the following error:
expression must be a modifiable lvalue
Here's struct code:
typedef struct {
int id;
char *entity[];
}entity;
Here's memory allocation in main function:
entity s;
s.entity= malloc(30 * sizeof(char *));
IDE underlines s.entity and pops the error I mentioned.
Please, help me out to solve this issue.
Your structure does not have a member called entity, only id and set.
You apparently want to allocate the whole structure. This type of struct member called flexible array member is useful if you want to allocate the whole structure in one malloc.
entity *s;
s = malloc(sizeof(*s) + 30 * sizeof(s -> set[0]));
This kind of struct members are very useful as you can realloc or free them in a single call.
Increase the size of the set array to 50
entity *tmp = realloc(s, sizeof(*s) + 50 * sizeof(s -> set[0]));
if(tmp) s = tmp;
Thats how you would allocate the pointers:
typedef struct {
int id;
char **set;
}entity;
int how_many_pointers = 30;
entity s;
s.set= malloc(how_many_pointers * sizeof(char *));
And for each pointer you would have to allocate the space for the corresponding string:
int i, string_size;
for(i = 0; i < how_many_pointers; i++)
{
printf("How many chars should have string number %d ?", i + 1);
scanf("%d", &string_size);
s.set[i] = malloc((string_size + 1) * sizeof(char)); // string + 1 due to space for '\0'
}

memcpy() not working as expected when copying pointers

I want to copy the content of a char **pointer to another pointer. My attempt was:
void test(char **arr, int len) {
printf("1: ");
printArr(arr, len);
char ***res = malloc(sizeof(char **));
res[0] = malloc(sizeof(char *) * len);
memcpy(&res[0], arr, len);
printArr(res[0], len);
Here I just wanted to copy the contents of arr, which holds several strings, to r[0] whereby len denotes the number of elements in arr. However, when inspecting res[0] I realised that it only stores two times null. As one can tell I'm a very beginner and have been learning C since a few days, so onc can expect simple mistakes.
char ***res = malloc(sizeof(char **));
res[0] = malloc(sizeof(char *) * len);
memcpy(&res[0], arr, len);
The first line allocates space for a single char ** and makes res point at it
The second line allocates space for an array of len pointers to char and makes res[0] point at it.
The third line copies len byes from arr over the top of the memory pointed at by res, overwriting the result of the second malloc call and then scribbling over memory after the block allocated by the first malloc call.
You probably actually want something like
mempy(res[0], arr, len * sizeof(char*));
which will copy an array of len pointers (pointed at by arr) into the memory allocated by the second malloc call.
If this is an array of C strings that you need deep copied:
char** array_deep_copy(char **arr, int len) {
// calloc() makes "allocation of N" calculations more clear
// that this is N allocations of char* becoming char**
char **res = calloc(len, sizeof(char*));
for (int i = 0; i < len; ++i) {
// Use strdup() if available
res[i] = strdup(arr[i]);
}
return res;
}
Note that this needs a proper release function that will go through and recursively free() those cloned strings or this leaks memory.
If you only need a shallow copy:
char** array_shallow_copy(char **arr, int len) {
char **res = calloc(len, sizeof(char*));
// memcpy(dest, src, size) is usually more efficient than a loop
memcpy(res, arr, sizeof(char*) * len);
return res;
}
This one doesn't need a recursive free(), you can just free() the top-level pointer and you're done. This one shares data with the original, so if any of those pointers are released before this structure is then you'll have invalid pointers in it. Be careful!

How do I dynamically allocate memory to a pointer array inside a structure

here is what i have in done so far
struct test_case {
int n;
int *test[];
};
struct test_case *test_case_struct = (struct test_case *)malloc(
sizeof(struct test_struct) + 100 * sizeof(int));
I need to allocate n pointers in the "test" pointer array. As far as i know i need to allocate space to the structure and then some more for the pointer array, but when i try to compile this, i get the error
invalid use of sizeof operator for to incomplete type struct test_struct
if someone could please inform me how i can take the value of n as a user input and have int *test [n] made possible.
Don't repeat type names. You already stumbled over your own code twice because you did that. You made the mistake of typing the wrong struct tag and confusing int* for int.
A more hardy allocation would look like this
struct test_case *test_case_struct =
malloc(sizeof (*test_case_struct) + sizeof (test_case_struct->test[0]) * 100);
This here will allocate the size of whatever test_case_struct points at, plus 100 more of whatever test_case_struct->test[0] should be. Now you can play with the structure definition without breaking this call to malloc. And if you do perform a breaking change (like renaming test), you'll be notified by your compiler promptly.
You need to change
sizeof(struct test_struct)
to
sizeof(struct test_case)
as test_struct is not the correct structure type.
In a better way, you can also use the already-declared variable name, like
struct test_case *test_case_struct = malloc(
sizeof (*test_case_struct) + n * sizeof(int*));
That said, you need to allocate memory worth of int *s, not ints, for the flexible member.
Also, below is a snippet which shows the count is taken as user input
int main(void)
{
int n = 0;
puts("Enter the count of pointers");
if (scanf("%d", &n) != 1) {
puts("Got a problem in the input");
exit (-1);
}
struct test_case *test_case_struct = malloc( sizeof(struct test_case) + n * sizeof(int*));
printf("Hello, world!\n");
return 0;
}
Currently you are using flexible array(aka zero length array).
Which can be allocated as below.
struct test_case *test_case_struct =
malloc(sizeof (*test_case_struct) + 100 * sizeof (int *));
Note missing * for int and typo sizeof(struct test_struct) in your code.
Alternatively you can use pointer to pointer as below.
struct test_case {
int n;
int **test;
};
struct test_case *test_case_struct = malloc(
sizeof(*test_case_struct));
test_case_struct->test = malloc(100 * sizeof(int *)); // Allocates 100 pointers

Difference between pointers when malloc

I usually make myself a struct and I allocate memory for the struct and sometimes for buffers inside the struct. Like so:
typedef struct A
{
char *buffer;
int size;
} A;
Then when I malloc for the struct I do this. (I learned not to cast the malloc return here on SO.)
X
A *a = malloc(sizeof(a));
a->buffer = malloc(10*sizeof(a->buffer));
What is the difference between X and Y this?
Y
A *a = malloc(sizeof(*a));
a->buffer = malloc(10*sizeof(a->buffer));
They seem to be doing the same thing.
Neither is correct, the second one doesn't even compile.
You want either of these:
A * a = malloc(sizeof(A)); // repeat the type
// or:
A * a = malloc(sizeof *a); // be smart
Then:
a->size = 213;
a->buffer = malloc(a->size);
you should typecast it (A *) because calloc or malloc return void *.
A *a=(a*)malloc(sizeof(A));
suppose you want to allocate memory for buffer for 10 characters
a->buffer=(char *)malloc(sizeof(char)*10);

Passing pointers for memory allocation inside a function?

I need to allocate arrays of structures in a bunch of different places in my program, thus putting the work inside a function (VS 2010). Compiler gives warning about uninitialized variable used. So how do I pass it, and how to declare it in the function. I've tried many variations of "&" and "*", to no avail.
(I apologize in advance if my code causes any form of nausea...I'm an English major.)
struct s_stream {
int blah;
};
void xxyz(void)
{
struct s_stream **StreamBuild;
char *memBlock_1;
xalloc(StreamBuild, memBlock_1, 20);
}
void xalloc(struct s_stream **StreamStruct, char *memBlock, int structCount)
{
int i = sizeof(struct s_stream *);
if ((StreamStruct=(struct s_stream **) malloc(structCount * i)) == NULL)
fatal("failed struct pointer alloc");
int blockSize = structCount * sizeof(struct s_stream);
if ((memBlock = (char *) malloc(blockSize)) == NULL)
fatal("failed struct memBlock alloc");
// initialize all structure elements to 0 (including booleans)
memset(memBlock, 0, blockSize);
for (int i = 0; i < structCount; ++i)
StreamStruct[i]=(struct s_stream *) &memBlock[i*sizeof(struct s_stream) ];
}
I'm not exactly sure I understand your question, but it seems like you want a function that will create a dynamically allocated array of struct s_stream objects and return them to the caller. If that's the case, it's pretty easy:
void easiest(void)
{
struct s_stream *array = malloc(20 * sizeof(struct s_stream));
}
You could move the malloc() off into its own function and return the pointer:
void caller(void)
{
struct s_stream *array = create_array(20);
}
struct s_stream *create_array(int count)
{
return malloc(count * sizeof(struct s_stream));
}
Or if you insist on passing the array as a parameter:
void caller(void)
{
struct s_stream *array;
create_array(&array, 20);
}
void create_array(struct s_stream **array, int count)
{
*array = malloc(count * sizeof(struct s_stream));
}
You are passing a copy of the pointer memBlock_1 to xalloc, so the address returned by malloc is written to the copy and never reaches the calling function. Since you presumably want the address to be available to xxyz in memBlock_1, you have to pass a pointer-to-pointer-to-char as the second argument,
void xalloc(..., char **memBlock, ...)
and call it with xalloc(..., &memBlock_1, ...);. In the body of xalloc, replace all occurrences of memBlock with *memblock, e.g. (*memblock = malloc(blockSize)) == NULL (no need to cast).
Analogously, the StreamStruct parameter of xalloc never changes the StreamBuild pointer-to-pointer-to-struct s_stream in xxyz. If I interpret your intentions correctly, you would also have to add a pointer layer to that parameter, void xalloc(struct s_stream ***StreamStruct, ..., ...), pass the address of StreamBuild in the call, xalloc(&StreamBuild, ..., ...) and dereference the pointer in the function body, e.g. (*StreamStruct = malloc(structCount * i)) == NULL.
Is there any reason you're not using a regular array? For example;
struct s_stream* streamArray = malloc(sizeof(s_stream*structCount));
Then you have an array of s_stream you can just access with streamArray[0] to streamArray[structCount-1] without dereferencing any extra pointers.

Resources