Is there any way to dynamically allocate memory for a structure in the definition of the structure, and if it can't be done, what is the best way to dynamically allocate memory for that structure ?
typedef struct user_t{
char user_name[30];
char email[50];
int movieswatched;
movie *movielist;
}user_t;
I want to allocate memory for movielist .
You can use a flexible array member:
typedef struct user_t{
char user_name[30];
char email[50];
int movieswatched;
movie movielist[]; // The flexible array member,
// must always be last and declared as an array without a size
}user_t;
A structure like this must be allocated dynamically (with e.g. malloc), for example as
user_t *my_user = malloc(sizeof *my_user + sizeof(movie) * 50); // Allocate space for 50 movies
You can't do it in the definition of the structure (which wouldn't make much sense anyway as you don't yet know the number of movies and because different user_t variables might have different number of movies).
You need to do it at runtime, for example like this:
user_t v;
...
v.movielist = malloc(sizeof(movie) * numberofmovies);
You could define a 'factory' function. That's a fancy name for a function that does both mallocs for you. Something like :
user_t *user_factory( const int movies_watched )
{
user_t *user = malloc(sizeof *my_user); // should check for NULL
user->movieswatched = movies_watched;
user->movielist = malloc(sizeof(movie) * movies_watched);
return user;
}
It's common to combine the mallocs, BTW, then you can use #someprogrammerdude's flexible array member approach (but still wrap it in the factory). The other advantage of their way is that it's harder to have an accidental memory leak.
If you really want an automatic variable as you have in your example, then you can have a half-way house of init (and deinit) functions:
void init_user_t( user_t *user, const int movies_watched )
{
user->movieswatched = movies_watched;
user->movielist = malloc(sizeof(movie) * movies_watched);
}
void deinit_user_t( user_t *user )
{
free( user->movielist );
user->movielist = NULL;
user->movieswatched = 0;
}
...
user_t my_user;
init_user_t( &my_user, 6 /*num_movies*/ );
Related
I'm going to try and keep this as brief as possible.
So I have two structs:
typedef struct someStruct named;
struct someStruct {
void *key;
void *value;
};
typedef struct anotherStruct namedToo;
struct anotherStruct {
named **table;
unsigned int size;
};
Okay great, now ingore any possible mistakes above, this is uneditable code.
Now I have two methods:
namedToo *init(float ignoreThis) {
namedToo *temp;
temp = malloc(sizeof(namedToo)); //some memory for the second struct
temp->table = malloc(sizeof(named)*100); //lets say this 100 is for 100 buckets/cells/named elements
return temp;
Method 2:
int insert(namedToo *temp, void* key, void* value) {
temp->table[0]->key = key; //My problem, I need to access the value and key inside named from the pointer inside namedToo. How can I do this?
}
The comment has my problem :
My problem, I need to access the value and key inside named from the pointer inside namedToo. How can I do this? I would need to change and grab value/key on their own from time to time.
The declaration named **table; says table is pointer to a pointer to named, or alternately an array of pointer to named. The latter is you seem to intend.
This allocation:
temp->table = malloc(sizeof(named)*100);
Allocates space for 100 named, but what you need are 100 named *, and each of those must point to a named. Given the definition of named this is likely enough space, however at this point you have an array of uninitialized pointers. Attempting to access them results in undefined behavior, which in this case manifests as a core dump.
You need to allocate space for an array of pointers, then initialize each of those to a single dynamically allocated instance of named. So you should be allocating space like this:
int i;
temp->table = malloc(sizeof(named *)*100);
for (i=0; i<100; i++) {
temp->table[i] = malloc(sizeof(named));
}
Then your insert method should work properly.
i have the following structure:
typedef struct Course {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} Course;
and the following function i need to implement:
void createReport(FILE* courses[], int numOfCourses, FILE* studentFile, char* reportFileName
as you can see i get an array of FILE*, each cell contains different file pointer.
my intention is to create an array that each cell is Course* type, and initialize each cell with a Course struct containing the data read from the courses files.
what is the correct way to declare it inside the function?
do i need to dynamically allocate memory for it, or it can be done in compilation?
i've tried
Course* course_array[numOfCourses] = {NULL};
Course* course_array[numOfCourses] = NULL;
but it won't compile.
thanks for your help
You declare an array of structs the same way you declare an array of ints or FILE *s:
Type variableName[numberOfElements];
Before C99 (and barring compiler specific extensions), creating an array with a variable number of elements on the stack wasn't supported. So make sure that you are targeting the correct standard. In your case, assuming C99 support, the following should work:
Course *course_array[numOfCourses];
Because you intend to initialize each of the elements in the array, there is no need to zero them out.
You would then access the elements like this:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 2;
/* etc. */
Now if you can't assume C99 support, things get a bit more tricky but not much:
Course *course_array = malloc(sizeof(Course *) * numOfCourses);
After that you can access course_array with the same array notation:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 42;
/* etc. */
Once you're doing with the array, you'll need to make sure that you free any of the memory that you allocated:
for (i = 0; i < numOfCourses; i++) {
free(course_array[i]);
}
/* If you malloc'd course_array, then you need this too */
free(course_array);
Course* course_array[numOfCourses] = {NULL};
This is good, but it creates array of Course *. So you need to allocate memory for each pointer in course_array before accessing it.
Something like
course_array[0] = malloc(sizeof(Course));
course_array[0]->course_id = someid;
When you define the array in the first place, you shouldn't need to allocate memory. You're defining the array on the stack, and the elements of the array are just pointers.
I think what you should do is first define the array, and then initialize each element with a malloc call. For example:
Course* course_array[numOfCourses];
for(int i = 0; i < numOfCourses, i++) {
course_array[i] = (Course*)malloc(sizeof(Course));
My favorite way:
typedef struct {
int a;
char b;
float c;
}DATA;
//then use typdef'ed DATA to create array (and a pointer to same)
DATA data[10], *pData;
//then, in function, you can initialize the pointer to first element of array this way:
int main(void)
{
pData = &data[0];
return 0;
}
Your example code would look like this:
typedef struct {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} COURSE;
//then in function:
COURSE course[numOfCourses]
I have an array inside a structure as below
struct st
{
....
int index[1];
....
}
How can I increase size of the array present inside structure to say 6, when I want to use the array inside a function.
Probably you looking for struct hack. Struct hack is a technique which allows you allocate additional memory for an array inside struct. Here is an example
struct str {
int value;
char ar[0];
};
int main()
{
struct str *s = malloc( sizeof(struct str) + 20 );
strncpy( s->ar,"abcd", 5);
printf("%s",s->ar);
return 0;
}
As array defined at the end of the struct, s->ar will get those additional 20 bytes added to sizeof(struct str) in malloc.
Edit as Daan Timmer noted, this technique can be applied only to last member of a struct.
You may try this:
struct st { ....
int index[6];
....
}
Also you may check function malloc() and realloc() in C
On a side note:
You may check STL container like std::vector which encapsulate the associated memory management.
An array defined that way exists on the stack. In order to dynamically change the size you will need to use allocate on the heap using malloc realloc and free.
I have a struct like this:
struct students {
char *names[MAXLENGTH];
};
How would I initialize the struct using malloc?
I tried
struct students student1 = {malloc(MAXLENGTH * sizeof(char**))};
but that gave me a "missing braces around initializer" error.
I'm new to C, so I'm not sure how to fix this.
You can allocate an instance of the struct like this:
struct students *pStudent = malloc(sizeof *pStudent);
This will allocate the array of string pointers (since it's part of the struct students), but not set the pointers to point at anything (their values will be undefined).
You need to set each individual string pointer, for instance like so:
pStudent->names[0] = "unwind";
This stores a pointer to a literal string. You can also allocate memory dynamically:
pStudent->names[1] = malloc(20);
strcpy(pStudent->names[1], "unwind");
of course, if you malloc() space you must remember to free() it. Don't mix literal strings with dynamically allocated ones, since it becomes impossible to know which ones need free()ing.
This is totally wrong struct students student1 = {malloc(MAXLENGTH * sizeof(char**))};
Try this code.
struct students* Student1 = malloc(sizeof(struct students ));
Student1->names[0] = malloc(sizeof(NAME_MAX));
scanf("%s",Student1->names[0]);//It may be first name. I think you want like this .
You have to use a for loop like this :
#define MAX_NAME_LENGTH 20
struct student s;
for(int i = 0; i < MAXLENGTH; ++i)
{
s.names[i] = malloc(sizeof(char) * MAX_NAME_LENGTH);
}
I am a newbie in C..I am trying to make some sense of how dynamic memory allocation works in case of structures and arrays..So like for example I have a code like..
struct Person
{
int id;
char *name;
char *place;
};
struct Database
{
struct Person *data_rows;
};
I want to dynamically allocate memory for both the character arrays name and place..and the array of struct data_rows..take their size as input..So what should ideally be the order of allocations and the proper syntax for the same? Thanks.
Well, "obviously" you need to get "struct Database" filled in first:
struct Database MyDatabase;
MyDatabase.data_rows=malloc(sizeof(MyDatabase.data_rows[0])*NumberOfPeople);
Ignoring the fact that I didn't check the malloc() for failure, this will give you an array of "struct Person", all uninitialized. So, most likely, you'll want to initialize them:
int i;
for (i=0; i<NumberOfPeople; i++)
{
struct Person* MyPerson;
MyPerson=&MyDatabase.data_rows[i];
MyPerson->id=i;
MyPerson->name=malloc(...);
/* Do something to store the name in MyPerson->name */
MyPerson->place=malloc(...);
/* Do something to store the place in MyPerson->name */
}
Now, the problem here is the "..." I put on the malloc. It's easy if you use a fixed size, but then you could have just declared your struct to be something like
struct Person
{
int id;
char name[100];
char place[200];
};
Basically, I just can't tell what the length of the names should be, hence I just typed it as "...".
Also, I just guessed what the "id" might be. Using the array index is actually somewhat pointless :-)
Of course, you don't have to do it all now. You could just set the name and place pointers to NULL and fill them in later, like when you're reading the data from a file, or whatever you're planning to do. Or you could just not initialize it here at all, if you're confident that your code always "knows" which fields are initialized and which ones are not.
I would highly recommend to write a functions person_new and person_free that would take care of structure memory management:
struct Person* person_new(char *name, char* place) {
struct Person* person = malloc(sizeof(struct Person));
person->name = strdup(name);
person->place = strdup(place);
return person;
}
void person_free(struct Person* person) {
free(person->name);
free(person->place);
free(person);
}
The best thing would be to convert your structs to classes, the following works also for structs...
You define a constructor and destructor in Database and in Person as following:
struct Person
{
Person(){
name = new char[256];
place = new char[256];
};
~Person(){
delete name;
delete place;
}
int id;
char *name;
char *place;
};
struct Database
{
Database(int nPersons){
data_rows = new Person[nPersons];
};
~Database(){
delete data_rows;
};
struct Person *data_rows;
};
or you can do this without a constructor and destructor and allocate all the stuff sequentially in your code, which is a very ugly way to do this!
as:
Database myData;
myData.data_rows = new Persons[40];
for(int i=0; i < 40; i++){
myData.data_rows[i].name = new char[256];
myData.data_rows[i].place = new char[256];
}
Note that data_rows[i] is nothing more than -> *(data_rows + i) which shifts the address of the pointer i times and then dereferences it!