dynamic allocation of struct with Malloc - c

Iam begginner in C and dynamic allocation,
i would like to allocate a memory for a structure.
struct MusicTitle has the list of a music title and the signer structure has the name of the songs and number of album that he made.
struct musicTitle() // structure of music title
{
Char* nameofsong;
char* Singer_name;
Char * release_year; }
musicTitle* allocteMusicTitle(){ // function to allocate memory for the music title struct
musicTitle* musicTitlePtr= (musicTitle*)malloc(sizeof(musicTitle*));
return musicTitlePtr;
}
struct singer{ // each singer has musictitle and albums
musicTitle* musicTitleofsigner
int* nbrAlbum;
}
singerMusic* allocateSingerMusic {
singerMusic* singerMusicPtr= (singerMusic*)malloc(sizeof(singerMusic*)); //allocate memory for singerMusic struct
}
my question is, do i need to allocate memory for nbrAlbum of the singer structure? or it gonna be done with allocateSingerMusic function ?
Thank you

There are few syntax and logical problems with this code. For example
Missing semicolon.
musicTitle* musicTitleofsigner
and allocating memory with size of pointer rather than size of struct.
singerMusic* singerMusicPtr= (singerMusic*)malloc(sizeof(singerMusic*));
I hope, you will correct those mistakes. Answer to your main question is that you need to allocate memory for nbrAlbum. This is the power and beauty of C language that no dynamic memory will be allocated automatically unless it is done explicitly.

Related

How can I access items in a dynamically allocated array of structs?

I'm in a class right now that works with C and one of my assignments requires that I work with a struct that my professor wrote for us. It's actually two structs, with one struct basically containing an array of the first struct.
Here's what they look like:
typedef struct cityStruct
{
unsigned int zip;
char *town
} city;
typedef struct zipTownsStruct
{
int *towns;
city **zips;
city *cities
} zipTowns;
And here's my function for allocating memory for the zipTowns structure:
void getArrs(zipTowns *arrs, int size)
{
arrs->towns = malloc(sizeof(int) * size);
arrs->zips = malloc(sizeof(city **) * size);
arrs->cities = malloc(sizeof(city *) * size);
}
From what I understand, what I'm doing here is allocating space in memory for a certain number of ints, city pointers, and city structures, based on the size variable. I understand that this is basically what an array is.
I'm having trouble with understanding how I can access these arrays and manipulate items in it. Writing this gives me an error:
strcpy(arrs.cities[0]->town, "testTown\0");
You can see what I'm trying to do here. I want to access each "City" in the zipTowns struct by index and insert a value.
How can I access the items in these dynamically allocated array of structures?
Think of x->y as (*x).y.
arrs is not a structure, it's a pointer to a structure, and cities is not a pointer to a pointer to a structure, it's just a pointer to a structure.
Use arrs->cities[0].town instead of arrs.cities[0]->town.
However, you're still not allocating enough room for these structures. This should make it clearer what you're doing with the allocations, and should also give you enough room for your data:
arrs->towns = malloc(sizeof(*arrs->towns) * size);
arrs->zips = malloc(sizeof(*arrs->zips) * size);
arrs->cities = malloc(sizeof(*arrs->cities) * size);
With the second and third, you were only allocating enough room for a pointer to be stored instead of the actual data type.
With this approach, you will be able to access from arrs->cities[0] to arrs->cities[9] and you also will be able to access the members of each city by doing arrs->cities[<number>].<member>.
You also do not need to intentionally null-terminate your strings. This is already done for you. Therefore, you can replace "testTown\0" with "testTown".

How to dynamically allocate memory for an array of structs

I am fairly new to C, and am having trouble figuring out how to allocate contiguous memory to an array of structs. In this assignment, we are given a shell of the code, and have to fill in the rest. Thus, I cannot change the variable names or function prototypes. This is what has been given to me:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct student {
int id;
int score;
};
struct student *allocate() {
/* Allocate memory for ten students */
/* return the pointer */
}
int main() {
struct student *stud = allocate();
return 0;
}
I'm just not sure how to go about doing what those comments say in the allocate function.
The simplest way to allocate and initialize the array is this:
struct student *allocate(void) {
/* Allocate and initialize memory for ten students */
return calloc(10, sizeof(struct student));
}
Notes:
calloc(), unlike malloc() initializes the memory block to all bits zero. Hence the fields id and score of all elements in the array are initialized to 0.
It would be a good idea to pass the number of students as an argument to the function allocate().
It is considered good style to free() allocated memory when you no longer need it. Your instructor did not hint that you should call free(stud); before returning from main(): while not strictly necessary (all memory allocated by the program is reclaimed by the system when the program exits), it is a good habit to take and makes it easier to locate memory leaks in larger programs.

What is the difference between using malloc to allocate memory to a struct pointer and pointing a struct pointer to a struct's memory address?

What is the difference between these two snippets of code?
// Structure
struct file {
int fileSize;
};
int main(void) {
// Variables
struct file *pFile = (struct file*) malloc(sizeof(struct file)); // Declare pointer of type struct file and allocate enough room
pFile->fileSize = 5;
free(pFile);
return 0;
}
and
// Structure
struct file {
int fileSize;
} file1;
int main(void) {
// Variables
struct file *pFile = &file1; // Declare pointer of type struct file and point to file1 struct
pFile->fileSize = 5;
return 0;
}
Is there something big I'm missing here? I'm thinking maybe face value wise these are the same but the underlying memory allocation is different? I just can't grasp it.
There are several differences here:
With malloc you can repeat the call multiple times, and get new valid memory area for your struct; there is only one statically allocated struct
Memory obtained through malloc needs to be freed at the end; statically allocated memory does not need freeing
Statically allocated struct is visible from multiple functions inside the translation unit; memory from malloc is not shared with other functions unless you pass a pointer to them explicitly.
In your first snippet pFile points to dynamically-allocated memory.
In your second snippet, pFile points to a global variable.
Other than the fact that you need to free the dynamic one yourself (which you haven't by the way), the way you interact with the struct is exactly the same in either case.

invalid use of flexible array ERROR in C

I have the following struct:
typedef struct dish_t {
const char *name;
const char *cook;
int maxIngredients;
bool tasted;
Ingredient *ingredients[];
}* Dish;
And the following initialization function:
Dish dishCreate(const char* name, const char* cook, int maxIngredients) {
if (name == NULL || cook == NULL || maxIngredients <= 0 )
{
return NULL;
}
Dish newDish=malloc(sizeof(*newDish));
newDish->name=malloc(strlen(name)+1);
newDish->name=name;
newDish->cook=malloc(strlen(cook)+1);
newDish->cook=cook;
newDish->maxIngredients=maxIngredients;
newDish->ingredients=malloc(maxIngredients*sizeof(Ingredient*));
newDish->tasted=false;
return newDish;
}
Ingredient is also a struct.
and on this line
newDish->ingredients=malloc(maxIngredients*sizeof(Ingredient*));
I get the error.
I'm trying to initialize an array of pointers to a struct...what am I doing wrong?
Thanks.
The struct member ingredients is an array of pointers, not a pointer. You cannot assign to an array in C; not to change its contents, and certainly not to change its address. The pattern <array> = malloc(...) makes no sense in C.
Just change the declaration to
Ingredient *ingredients;
Forget about flexible member; that's a memory allocation strategy that won't add to the semantics or quality of your program.
In some kinds of programs, flexible arrays at the end of a structure can be a useful
optimization, since they reduce the number of calls to the allocator: a header structure plus some variable data can be allocated in a single malloc call and released in a single free call.
This doesn't achieve anything semantically interesting in the program, and naive use of this approach can make programs slower and waste memory, since two or more objects with flexible data at the end have to have their own copies of the data in situations where a program that uses a pointer could efficiently share that data.
The problem is that you try to make a flexible array of pointers, and then you try to create this using malloc, which is not what you're supposed to do.
With flexible arrays in a structure, you're supposed to make the initial allocation of the structure longer, to fit the number of elements in the array.
If you're going to use malloc for the array, you might as well use a normal pointer.
To explain what I mean:
typedef struct dish_t {
...
Ingredient ingredients[];
}* Dish;
...
Dish myDish = malloc(sizeof(*myDish) + sizeof(Ingredient) * 10);
The above malloc allocates the structure and enough space for ten entries in the array.

Allocation of memory for char array

Let's say you have-
struct Person {
char *name;
int age;
int height;
int weight;
};
If you do-
struct Person *who = malloc(sizeof(struct Person));
How would C know how much memory to allocate for name variable as this can hold a large number of data/string? I am new to C and getting confused with memory allocation.
It won't know, You will have to allocate memory for it separately.
struct Person *who = malloc(sizeof(struct Person));
Allocates enough memory to store an object of the type Person.
Inside an Person object the member name just occupies a space equivalent to size of an pointer to char.
The above malloc just allocates that much space, to be able to do anything meaningful with the member pointer you will have to allocate memory to it separately.
#define MAX_NAME 124
who->name = malloc(sizeof(char) * MAX_NAME);
Now the member name points to an dynamic memory of size 124 byte on the heap and it can be used further.
Also, after your usage is done you will need to remember to free it explicitly or you will end up with a memory leak.
free(who->name);
free(who);
Don't assume that the memory storing the pointer for name is the same as the memory storing the data for name. Assuming a 4 byte word size, you have the following:
char * (4 bytes)
int (4 bytes)
int (4 bytes)
int (4 bytes)
================
total: 16 bytes
which is: sizeof(char*) + sizeof(int) + sizeof(int) + sizeof(int). C knows the size because you've told it the size of the elements in the struct definition.
I think what you are confused about is the following:
The contents at the char * will be a memory location (e.g. 0x00ffbe532) which is where the actual string will be stored. Don't assume that the struct contents are contiguous (because of the pointer). In fact, you can be pretty sure that they won't be.
So, to reiterate, for an example struct Person (this is just an example, the locations won't be the same in a real program.)
location : [contents]
0x0000 : [0x00ffbe532]
0x0004 : [10]
0x0008 : [3]
0x000C : [25]
0x00ffbe532 : [I am a string\0]
The name member is just a pointer. The size of a pointer varies with the underlying architecture, but is usually 4 or 8 bytes nowadays.
The data that name can point to (if assigned later) should be laid out in an area that does not coincide with the struct at all.
At the language level, the struct doesn't know anything about the memory that the name member is pointing to; you have to manage that manually.
It allocates memory for the just the pointer to a char. You need to do a separate allocation for the contents.
There are other options although:
If you are OK with having a fixed sized maximum length, you can do:
struct Person {
char name[PERSON_NAME_MAX_LENGTH+1];
int age;
int height;
int weight;
};
And allocate it as in your example.
Or you can declare a variable sized struct, but I wouldn't recommend this as it is tricky and you cannot have more than one variable size array per struct:
struct Person {
int age;
int height;
int weight;
char name[]; /*this must go at the end*/
};
and then allocate it like:
struct Person *who = malloc(sizeof(struct Person) + sizeof(char)*(name_length+1));
It will allocate 4 bytes for the name pointer, but no space for the "real" string. If you try to write there you will seg fault; you need to malloc (and free) it separately.
Using string (in C++) can save you some headache
For pointers the struct is allocated enough memory just for the pointer. You have to create the memory for the char* and assign the value to the struct. Assuming you had char* name somewhere:
struct Person *who = malloc(sizeof(struct Person));
who->name = malloc((strlen(name)+1) * sizeof(char));
strcpy(who->name, name)
It doesn't. You have to do that too.
struct Person *who = malloc(sizeof(struct Person));
who->name = malloc(sizeof(char) * 16); /* for a 15+1 character array */
You have a pointer to a name character array in your struct, ie. it will consume that much bytes that are needed to represent a memory address.
If you want to actually use the field, you must allocate additional memory for it.
Pointer members occupy one word in my experience (the address on witch the data actually resides) so the size will probably be 16 bytes (assuming one word is 4 bytes)
As the man said above you need to separately allocate memory for *name witch will free memory someplace else for the size you desire
I think you should also need to allocate memory for the name attribute

Resources