Initialize array dynamically in struct - c

How can I initialize array dynamically in struct Course? I need to make array of student structs.
typedef struct {
char *name;
char ID[9];
} Student;
typedef struct {
Student *students = //here
} Course;

Initializing in a struct declaration isn't possible, and it wouldn't make sense in C -- you don't have an object of that struct yet.
Assuming you need a variable amount of Students in your array, there are different ways to model that. A typical approach could look like:
typedef struct {
size_t capacity;
size_t count;
Student **students;
} Course;
With the double-pointer, this is designed to hold "references" to the Student objects (instead of the Student objects themselves). I have to guess this is what you need. You could allocate and manage that for example like this:
#define CHUNKSIZE 16 // reserve space for this many Students at once
Course *Course_create(void)
{
Course *course = malloc(sizeof *course);
if (!course) return 0;
course->capacity = CHUNKSIZE;
course->count = 0;
course->students = malloc(CHUNKSIZE * sizeof *(course->students));
if (!course->students)
{
free(course);
return 0;
}
return course;
}
int Course_addStudent(Course *course, const Student *student)
{
if (course->count == course->capacity)
{
// allocate more memory if needed
size_t newcapa = course->capacity + CHUNKSIZE;
Student **newstudents = realloc(course->students, newcapa * sizeof *newstudents);
if (!newstudents) return 0; // error
course->capacity = newcapa;
course->students = newstudents;
}
course->students[course->count++] = student;
return 1; // success
}
A proper cleanup could look like this:
void Course_destroy(Course *course)
{
if (!course) return;
free(course->students);
free(course);
}

Student *students is just a pointer to Student. You cannot and should not initialize the pointer.
Method1
You need to first allocate memory for the struct and then initialize it.
// in main
Course courses;
courses.students = malloc(sizeof(Student));
if (courses.students != NULL_PTR)
{
courses.students.name = malloc(100); // 100 would be the size of the name you want to store
if (courses.students.name != NULL_PTR)
{
courses.students.name = "Default Name";
courses.students.ID = 12345;
}
}
Method2
This method removes the pointers from the structs in the first place. It changes the definition of the structure.
Since there are no pointers involved, you can safely inialize the structure on definition.
typedef struct {
char name[100];
char ID[9];
} Student;
typedef struct {
Student students;
} Course;
int main(void)
{
Course courses = {{"Default Name",12345}};
// other code here
}

Related

How do allocate dynamic memory for a array inside a structure in C and How to access it

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

Dynamic allocation of union of structs

I am trying to create a union of 2 structs (dfp and affine) and want to allocate them dynamically. I am getting errors in creating particular struct array inside union. Am I declaring union in right way?
#include <stdio.h>
#include <stdlib.h>
struct{
int fp;
}dfp;
struct{
int scale;
int zp;
}affine;
union{
struct dfp *df;
struct affine *af;
}quant;
struct member{
int total;
union quant arr;
};
int main(void) {
// your code goes here
struct member* ptr;
ptr = (struct member *)malloc(sizeof(struct member));
ptr->total = 2;
int type = 0;
if(!type){
ptr->arr->df = (struct dfp*)malloc(ptr->total*sizeof(struct dfp)); //error
for(int i=0;i<2;i++){
ptr->arr->df->fp[i] = 10;
}
}
else{
ptr->arr->af = (struct affine*)malloc(ptr->total*sizeof(struct affine)); //error
for(int i=0;i<2;i++){
ptr->arr->af->scale[i] = 10;
ptr->arr->af->zp[i] = 20;
}
}
return 0;
}
Most issues have already been pointed out by others separately. This is my attempt at writing a complete answer with explanations and advice.
First off, please check your exact compiler warnings and errors. These are your best help in resolving these kind of issues.
The program does not contain a union of structs, but a union of pointers to structs.
The program's definitions are not correct. Taking dfp as an example. This, struct { int fp; } dfp;, defines an anonymous struct with the the variable name dfp. The name of the struct should go before the struct declaration list, e.g. struct dfp { int fp; };. See here or see the C standard specifications.
Judging by the code in main, the member variables of the structs should be arrays of size 2 instead of single ints.
The operator -> is for "member access using a pointer". Since arr is not a pointer, use a dot (.) to access its members. See here.
Dynamically allocated memory must be free'd, or else the program will have one or more memory leaks.
Here is the full code with all mentioned corrections:
#include <stdio.h>
#include <stdlib.h>
struct dfp {
int fp[2];
};
struct affine {
int scale[2];
int zp[2];
};
union quant {
struct dfp *df;
struct affine *af;
};
struct member {
int total;
union quant arr;
};
int main(void) {
struct member* ptr;
ptr = (struct member *)malloc(sizeof(struct member));
ptr->total = 2;
int type = 0;
if(!type) {
ptr->arr.df = (struct dfp*)malloc(ptr->total*sizeof(struct dfp));
for(int i=0;i<2;i++){
ptr->arr.df->fp[i] = 10;
}
}
else {
ptr->arr.af = (struct affine*)malloc(ptr->total*sizeof(struct affine));
for(int i=0;i<2;i++){
ptr->arr.af->scale[i] = 10;
ptr->arr.af->zp[i] = 20;
}
}
if(!type) {
free(ptr->arr.df);
}
else {
free(ptr->arr.af);
}
free(ptr);
}
Correct the struct definition as below:
struct dfp {
int fp;
};
struct affine{
int scale;
int zp;
};

How to allocate memory for a structure inside another structure?

I have 2 structures in my C code. I want to write a hash function with these 2 structures. So I want to initialize my data null in first case. My code is
struct HashNode
{
char username[20];
char password[20];
};
struct HashTable
{
int size;
struct HashNode *table;
};
HashTable *initializeTable(int size)
{
HashTable *htable;
if (size < MIN_TABLE_SIZE)
{
printf("Table Size Small\n");
return NULL;
}
htable = (HashTable *)malloc(sizeof(Hashtable));
if (htable == NULL)
{
printf("memory allocation pblm\n");
return NULL;
}
htable->size = size;
}
How can I allocate memory for htable->table with that size? I have code in C++ like htable->table = new HashNode [htable->size];. How can I write this in C using malloc?
You can allocate the memory in this way
htable->table = malloc(size*sizeof(HashNode))

initialization of flexible array of struct pointers in a struct in c

I'm learning hashtable data structures and I want to make a hashtable with a flexible length array of pointers to struct Link (linked list pieces), so that hashtable initialization will set the array to be a length input into the initialization function.
At first I was getting the error "flexible array not at the end of struct". When its at the end (as shown) the program crashes (but it still compiles). This is my code:
typedef struct Link{
int key;
char *name;
struct Link *next;
} Link;
typedef struct HashTable{
int numberOfEntries;
int numberOfBuckets;
Link *Table[];
} HashTable;
HashTable *hashtableInit(int size){
HashTable *newHT = malloc(sizeof(HashTable));
if (newHT != NULL){
newHT->numberOfEntries = 0;
newHT->numberOfBuckets = size;
for (int i = 0; i < newHT->numberOfBuckets; i += 1){
newHT->Table[i] = NULL;
}
return newHT;
} else {
printf("Error in memory allocation.\n");
fflush(stdout);
return NULL;
}
}
}
It works if I set the array to a constant and input the same value into the init function:
#define SIZE 11
typedef struct Link{
int key;
char *name;
struct Link *next;
} Link;
typedef struct HashTable{
Link *Table[SIZE];
int numberOfEntries;
int numberOfBuckets;
} HashTable;
HashTable *hashtableInit(int size){ // works if SIZE is passed into function as size parameter
HashTable *newHT = malloc(sizeof(HashTable));
if (newHT != NULL){
newHT->numberOfEntries = 0;
newHT->numberOfBuckets = size;
for (int i = 0; i < newHT->numberOfBuckets; i += 1){
newHT->Table[i] = NULL;
}
return newHT;
} else {
printf("Error in memory allocation.\n");
fflush(stdout);
return NULL;
}
}
}
The second code block works perfectly. Any insights would be greatly appreciated. Thanks for your time.
Chris
You should allocate memory as
HashTable *newHT = malloc(sizeof *newHT + size * sizeof newHT->Table[0]);
Your
HashTable *newHT = malloc(sizeof(HashTable));
is wrong, because no space is given for the flexible array member. Should probably be
HashTable *newHT = malloc(sizeof(HashTable)+size*sizeof(Link*));

Allocate struct from function in C

I'm having issues writing a function that allocates a struct in C. Ideally, I want to have the function fill the fields of the struct with parameters passed into it.
I have defined the struct in my header file like so:
typedef struct {
char name[NAME_SIZE]; //Employee name
int birthyear; //Employee birthyear
int startyear; //Employee start year
} Employee;
And this is what I have for my function currently:
void make_employee(char _name, int birth_year, int start_year) {
Employee _name = {_name,birth_year,start_year}; //allocates struct with name
} /* end make_employee function */
Any advice on how to accomplish this?
The problem with your current code is that the struct your creating is created on the stack and will be cleaned up as soon as the function returns.
struct foo
{
int a;
int b;
};
struct foo* create_foo( int a, int b )
{
struct foo* newFoo = (struct foo*)malloc( sizeof( struct foo ) );
if( newFoo )
{
newFoo->a = a;
newFoo->b = b;
}
return newFoo;
}
This will get you a heap allocated object. Of course, you'll need a function to free that memory or this is a memory leak.
void destroy_foo( struct foo* obj )
{
if( obj )
free( obj );
}
void print_foo( struct foo* obj )
{
if( obj )
{
printf("foo->a = %d\n",obj->a);
printf("foo->b = %d\n",obj->b);
}
}
(btw, this style gets you part of the way toward an "object oriented" C. Add some function pointers to the struct (to get polymorphic behavior) and you have something interesting; though I'd argue for C++ at that point.)
You have to return a pointer allocated via malloc:
Employee* new_employee(char *_name, int birth_year, int start_year) {
struct Employee* ret = (struct Employee*)malloc(sizeof(struct Employee));
ret->name = _name;
ret->birth_year = birth_year;
ret->start_year = start_year;
return ret;
}
two more things: (1) you should make the struct definition of name a char* instead of char[NAME_SIZE]. Allocating a char array makes the struct much bigger and less flexible. All you really need is a char* anyway. And (2) change the function definition to char*.
Why does the make Employee return void? You need to return the Employee from the make_employee function!
Are you having trouble with the compiler complaining about the x = {a,...} syntax? Write it the long way then: Emp e; e.field1 = a; ...
Are you having weird overwriting / bogus numbers problems? If you allocate a struct in the function it will become invalid (and prone to being overwriten) as soon as the function returns! To go around this you either have to:
Return a copy of the struct (this is OK for small structs):
Employee make_emp(int a){
Emp emp; //Allocate temporary struct
emp.filed1 = a; //Initialize fields;
return emp; // Return a copy
}
Allocate the struct in the heap instead and deal with it through references (ie.: pointers) instead:
Employee* make_emp(int a){
Emp* emp = malloc(sizeof(Emp)); //Allocate the struct on the heap
//And get a reference to it
emp->filed1 = a; //Initialize it
return emp; //Return the reference
}
Don't forget to free() the Employee after you are done with it in this case!
Employee * make_employee(char *_name, int birth_year, int start_year)
{
Employee *employee;
if (employee = (struct Employee *)memalloc(sizeof(Employee)) == NULL)
{
return NULL;
}
else
{
strcpy(&(employee->name), _name);
employee->birthyear = birth_year;
employee->startyear = start_year;
return employee;
}
}

Resources