I am having trouble figuring out how to make a hard-coded array heap allocated.
Imagine I have the structures:
struct my_struct
{
...
};
struct holder
{
my_struct *array_of_struct;
...
};
Now to create an instance of struct holder though, the array of struct my_struct has to be hard-coded, such as:
struct holder *new_holder()
{
struct holder *my_holder = malloc(sizeof(struct holder));
if (my_holder == NULL)
exit(-1);
struct my_struct arr[] = {mystruct_instace_1, mystruct_instance_2, ...};
holder->array_of_struct = arr;
return holder;
}
This assignment though wont work, because its pointing to arr which is stack allocated. How would I go about making this assignment of holder->array_of_struct heap allocated?
The super-lazy way to do it is just copy the array into a buffer from malloc(), as follows:
struct my_struct arr[] = {mystruct_instace_1, mystruct_instance_2, ...};
holder->array_of_struct = malloc(sizeof(arr));
assert(holder->array_of_struct);
memcpy(holder->array_of_struct, arr, sizeof(arr));
return holder;
By "super-lazy" I mean "minimum number of lines of code written".
Related
How to access the array elements after allocate the memory.
I cont able to allocate a memory inside a structure how do perform that:
How do allocate dynamic memory for a array inside a structure in C and How to access it
#include<stdio.h>
#include<stdlib.h>
struct student{
int *arr = (int*) malloc(10 * sizeof(int));
int reg;
};
void main()
{
struct student *ptr = (struct student*) malloc(sizeof(struct student));
ptr->reg = 10;
ptr->arr[0] = 100;
printf("register no : %d\n",ptr->reg);
printf("register no : %d\n",ptr->arr[0]);
return ;
}
You can't give a default value for struct members.
Once you have an instance of struct student, then you can allocate memory to the arr member.
#include <stdio.h>
#include <stdlib.h>
struct student{
int *arr;
int reg;
};
int main()
{
struct student *ptr = malloc(sizeof(struct student));
ptr->reg = 10;
ptr->arr = malloc(10 * sizeof(int))
ptr->arr[0] = 100;
printf("register no : %d\n",ptr->reg);
printf("register no : %d\n",ptr->arr[0]);
return 0;
}
One common pattern is to create a function that does the allocation and freeing of the struct (error handling not included) for you:
#include <stdlib.h> // malloc(), free()
struct student {
int *arr;
int reg;
};
// ...
struct student *student_allocate(int reg_n) {
struct student *student = malloc(sizeof(* student));
student->arr = malloc(sizeof(int) * reg_n);
student->reg = reg_n;
return student;
}
void student_free(struct student *student) {
free(student->arr);
free(student);
}
// ...
int main() {
struct student *student = student_allocate(10);
// do something with student
student_free(student);
}
In addition to #dbush's answer, you can also reorder your struct to make the pointer as a 1-sized array in the last field and allocate the whole stuff at once:
struct student {
int reg; // First fields are the general info
// any other fixed-size fields
int arr[1]; // LAST field is the array
};
Then,sizeof(struct student) is the size of the "general info" plus the size of an int, so you can allocate whatever amount of bytes for arr in one call to malloc() and arr points to whatever memory you allocated:
int nreg = 10;
struct student *pt = malloc(sizeof(struct student) + (nreg - 1) * sizeof(int));
pt->reg = nreg;
pt->arr[3] = 12; // pt->arr is the array you allocated with nreg*sizeof(int)
In the structure, we may only have a pointer to the array we want to store in memory or a pointer to an array of a fixed size (For example: int arr[10];) The array will have to be dynamically allocated later if we choose the first option.
We cannot give structure members default values or handle allocation of memory in the structure itself. I believe this is what you're looking for:
#include<stdio.h>
#include<stdlib.h>
struct student {
int *arr;
int reg;
};
void main()
{
struct student *ptr = (struct student*) malloc(sizeof(struct student));
ptr->reg = 10;
ptr->arr = (int*) malloc(10 * sizeof(int));
ptr->arr[0] = 100;
printf("register no : %d\n",ptr->reg);
printf("register no : %d\n",ptr->arr[0]);
return;
}
I'm getting the error for p->letter = 'A' and p->age = '9'. I don't know what is going wrong.
#include<stdio.h>
#include<stdlib.h>
struct player {
char letter;
int age;
};
typedef struct player *player_t;
int main (void)
{
player_t* p;
p = (player_t*)malloc(1 * sizeof(player_t));
if (p == NULL)
{
/* EDITED by #ahmedmasud removed original printf line for language */
printf("Unable to allocate\n");
return 1;
}
p->letter = 'A';
p->age = '9';
free(p);
return 0;
}
As many folks have pointed out you have a problem because in using typedef you went one step too far :-). Using typedef to recast types is meant for increasing clarity whereas the way you're using it decreases clarity.
Let me first show your example with the correct approach:
#include <stdio.h>
#include <stdlib.h>
struct player {
char letter;
int age;
};
/* typedef struct player *player_t; NOT NEEDED */
int main (void)
{
struct player *p;
p = malloc(sizeof(*p)); /* used *p for sizeof instead of struct player */
if (p == NULL)
{
fprintf(stderr, "Unable to allocate memory\n");
return 1;
}
p->letter = 'A';
p->age = '9';
free(p);
return 0;
}
When to use typedef foo_t bar_t
When it makes things clearer, e.g. stdint.h does this for integers. Say, you want a 32-bit unsigned int, you would use uint32_t which is appropriately typedef'd for various architectures to give you what you expect.
When NOT to use typedef struct foo foo_t
Pretty much all the time.
When it's OK to use typedef struct foo foo_t
Now for the reasons behind the changes, typedef struct foo foo_t is discouraged except when struct foo is opaque, typically when you are writing a C API where the structure is accessed through predefined access functions that have a longer life than internal structure.
Why use sizeof(*p) instead of sizeof(struct player) ?
In case, for some reason, you decide to change what *p is then all you have to do is change the declaration, and not worry that it's not going to get appropriately allocated.
This is an example of why you shouldn’t typedef a pointer.
player_t is a typedef for struct player *. You then define p as a player *, which means the full type of p is struct player **. The fact that you had a pointer hidden in a typedef ended up confusing you, and it can similarly confuse others who read your code.
Remove the pointer from the typedef and it will work as expected:
typedef struct player player_t;
You typedef
typedef struct player *player_t;
... so player_t is a type of pointer to struct player.
Then you define a variable:
player_t* p;
p is a pointer to pointer to struct player. Remove the *.
player_t* p; is not a pointer to struct player; it is a pointer to a pointer to struct player. Remove the * from the variable declaration and from the type cast before the call to malloc (you do not need that cast, anyway).
Change these two lines:
player_t* p;
p = (player_t*) malloc(1*sizeof(player_t));
into:
player_t p;
p = (player_t) malloc(1*sizeof(struct player));
p is of type player_t, which is already defined as a pointer to a player. No need for another * in its definition. Also, you need to allocate the size of the original struc, not the size of the pointer (sizeof(player_t) is the size in bytes of a pointer, not the size of the struct player).
Apart from what others pointed, Firstly typedef a pointer variable is not considered as good practice as hiding the * makes the code hard to read. Read Is it a good idea to typedef pointers?
Though if you want to typedef a pointer then do like below
typedef struct player {
char letter;
int age;
}player_t, *player_p; /* player_t is normal struct & player_p is pointer struct, here when someone see _p at the end of variable means it has * */
Next you need to allocate memory for player_p for e.g
player_p ptr = malloc(sizeof(struct player)); /* here don't take like "player_p *ptr" as player_p is already a pointer to struct */
if(ptr == NULL) {
/* error handling #TODO */
}
Later you can access structure member like
ptr->letter = 'A';
ptr->age = '9'; /* age is integer member, you may want to assign integer value directly like 57 instead of '9' */
And free the dynamically created memory by calling free().
free(ptr);
Sample code
typedef struct player {
char letter;
int age;
}player_t, *player_p;
int main(void) {
player_p ptr = malloc(sizeof(struct player));
if(ptr == NULL) {
/* error handling #TODO */
}
ptr->letter = 'A';
ptr->age = 50;
printf("%c .. %d \n",ptr->letter,ptr->age);
free(ptr);
return 0;
}
struct DynamicArray {
int allocated;
int used;
int *array;
}; typedef struct DynamicArray DynamicArray;
DynamicArray * ArrayCreate(int initialSize) {
DynamicArray *array;
(*array).array = (int*)malloc(initialSize*sizeof(int)); //Debugger points this line.
if((*array).array == NULL) {
return NULL;
}
(*array).allocated = initialSize;
(*array).used=0;
return array;
}
I am trying to make my own library for dynamic arrays. Just to learn and improve myself. Please review my code. What am I doing wrong?
You are de-referencing an uninitialized pointer here:
DynamicArray *array; // uninitialized
(*array).array = .... // ooops
You need to make array point to some memory you can write to. For example
DynamicArray *array = malloc(sizeof(DynamicArray));
First use this :
DynamicArray *array;
array = (DynamicArray *)malloc(sizeof(struct DynamicArray));
array->array = ...
If you don't initialize a point you can't dereference it because its point to NULL.
I would like to allocate memory for arrays that are members of a struct I need to use, inside a function that takes the struct as an argument.
arg->A.size=(int*) malloc(N*sizeof(int));
will not compile (request for member 'size' is something not a structure.
arg->A->size=(int*) malloc(N*sizeof(int));
will throw a segmentation fault error
Any help will be appreciated.
Here is the code, thanks:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// struct A
struct A {
int dim; // dimensions
int* size; // points per dim array
double* val; // values stored in array
int total; // pow(size,dim)
};
// struct B that uses A
struct B {
int tag;
struct A* A;
};
int function_AB(struct B* B);
int main(void){
struct B B;
function_AB(&B);
return 0;
}
int function_AB(struct B* arg){
int N=10;
arg->tag=99;
printf("tag assigned = %d \n", arg->tag);
arg->A->size=(int*) malloc(N*sizeof(int));
return 0;
}
You simply haven't allocated memory for struct A *A. Before assigning anything to A->size you would first need to do something like
B->A = malloc(sizeof(struct A));
The second case is correct, but crashes because the A inside the B declared in main has not been assigned a value. You probably want something like
struct A A;
struct B B;
B.A = &A;
function_AB(&B);
When you have structure pointer in another structure, first you need to allocate memory for that. then allocate the memory for structure members!
struct B {
int tag;
struct A* A;
};
Here A is a pointer to a structure called A. First allocate memory for this, then allocate memory for the elements of struct A
arg->A = malloc(sizeof(struct A));
then do-
arg->A->size = malloc(N*sizeof(int));
Try the following changes in your int function_AB(struct B* arg)-
int function_AB(struct B* arg){
int N=10;
arg->tag=99;
printf("tag assigned = %d \n", arg->tag);
arg->A = malloc(sizeof(struct A)); // First allocate the memory for struct A* A;
arg->A->size = malloc(N*sizeof(int)); // Allocate the memory for struct A members
arg->A->val = malloc(N*sizeof(double));
// do your stuff
// free the allocated memories here
free(arg->A->size);
free(arg->A->val);
free(arg->A);
return 0;
}
And don't cast the result of malloc()!
If I have several linked structures in C like:
struct structA {
int a;
int b;
struct structA *next;
}
struct structB {
char a;
int b;
struct structB *next;
}
and I dynamically allocate memory like this:
struct structA *mystructA = (struct structA*) malloc(sizeof(struct structA));
mystructA->next = (struct structA*) malloc(sizeof(struct structA));
struct structB *mystructB = (struct structB*) malloc(sizeof(struct structB));
mystructB->next = (struct structB*) malloc(sizeof(struct structB));
do I always have to free it for each struct type like this:
struct structA *p, *pNext;
for (p = mystructA; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
struct structB *p, *pNext;
for (p = mystructB; p != NULL; p = pNext) {
pNext = p->next;
free(p);
}
or is there any generic solution? I assume there is no other solution because the free() procedure must know how many bytes have to be freed. But maybe I'm wrong and someone can teach me better.
The standard way is to make the "list part" the first element of the structure, and let each derived struct share this same prefix. Since the first element is guaranteed to be placed at offset zero this wil work.
Example snippet:
#include <stdlib.h>
#include <string.h>
struct list {
struct list *next;
};
struct structA {
struct list list;
int a;
int b;
};
struct structB {
struct list list;
char a;
int b;
};
void *create_any(size_t size)
{
struct list *this;
this = malloc (size);
if (!this) return this;
memset(this, 0, size);
this->next = NULL;
return this;
}
void free_all_any(struct list **lp) {
struct list *tmp;
while ((tmp = *lp)) { *lp = tmp->next; free(tmp); }
}
#define CREATE_A() create_any(sizeof(struct structA))
#define CREATE_B() create_any(sizeof(struct structB))
#define FREE_A(pp) free_any((struct list **) pp)
#define FREE_B(pp) free_any((struct list **) pp)
int main(void)
{
struct structA *ap;
struct structB *bp;
ap = CREATE_A ();
bp = CREATE_B ();
// some code here ...
FREE_A( &ap);
FREE_B( &bp);
return 0;
}
This is more or less the method used in the linux kernel, but a lot more preprocessor magic is used there. (and there is no malloc there, obviously)
Since free() accepts pointers to void * and structA and structB both have the same size, you can pass both pointer types.
This is, however, not optimal in terms of elegance. You should think about the following questions:
Why do you have two different structs with the same members?
Why do you not have a generic list item type, such as the following:
struct list_node {
void *data;
struct list_node *next;
}
Actually, this is a very interesting question. The part is true that you have to free() each struct type individually, as they have been malloc()-ed individually, and each memory block has been allocated specifically for that type.Also, on some systems char and int have different storage sizes, but you can try a solution like Phillip provided. For more info, read about the doom memory engine. On a side note, please don't cast malloc() in C. The funny thing is that once the program is terminated, the operating system will reclaim the memory, so if you only deallocate the structures near the end of the program, when you don't need them anymore, it may not be necessary to free() them