Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:
struct line* array = malloc(number_of_elements * sizeof(struct line));
In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().
Note that's it's better style to use:
sizeof(*array)
instead of:
sizeof(struct line)
The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.
Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:
typedef struct line
{
char* addr;
char* inst;
} line;
You can then just do:
line* array = malloc(number_of_elements * sizeof(*array));
Of course don't forget to also allocate memory for array.addr and array.inst.
Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:
struct line* array = malloc(number_of_elements * sizeof(struct line));
In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().
Note that's it's better style to use:
sizeof(*array)
instead of:
sizeof(struct line)
The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.
Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:
typedef struct line
{
char* addr;
char* inst;
} line;
You can then just do:
line* array = malloc(number_of_elements * sizeof(*array));
Of course don't forget to also allocate memory for array.addr and array.inst.
For what you have described, You do not need to allocate memory for your struct, rather, you need to allocate memory for the members char *addr;, and char *inst;. If you want to have a single copy of that structure, the first section of code illustrates how to initialize, and assign values. If you want an array, the second code example illustrates the differences.
This illustrates how to allocate memory for the members of a single struct line:
typedef struct
{
char* addr;
char* inst;
}LINE;
LINE line;
int main(void)
{
strcpy(line.addr, "anystring"); //will fail
line.addr = malloc(80);
line.inst = malloc(80);
strcpy(line.addr, "someString");//success;
strcpy(line.inst, "someOtherString");//success;
}
For array of struct line...
typedef struct
{
char* addr;
char* inst;
}LINE; //same struct definition
LINE line[10]; //but create an array of line here.
int main(void)
{
int i;
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
//when done, free memory
for(i=0;i<10;i++)
{
free(line[i].addr);
free(line[i].inst);
}
}
Added to address comment
Addressing the comment under this answer from @Adam Liss, the following code illustrates the following improvements using strdup(): 1) Uses only memory needed. 2) Performs memory creation and copy operations in one step, so the the following blocks:
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
Become:
for(i=0;i<10;i++)
{
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
}
One more note: Error handling was not included in examples above to avoid muddling up focus on the main concepts: But for the sake of completeness, because both malloc() and strdup() can fail, actual usage for each of these two functions, should include a test before using, eg:
Rather than
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
The code should include
line[i].addr = strdup("someString");
if(!line[i].addr)
{
//error handling code here
}
line[i].inst = strdup("someOtherString");
if(!line[i].inst)
{
//error handling code here
}
How to malloc arrays inside structs?
c - malloc an array of struct pointers - Stack Overflow
How to malloc for an array of structs in c - Stack Overflow
c - How to free() an array of structs allocated by malloc()? - Stack Overflow
Videos
I would like to have a struct containing several dynamically allocated arrays. I've tried several variations of the following code:
#include<stdio.h>
#include<stdlib.h>
struct rectangle
{
int
width,
height;
int*
arr1,
arr2;
};
int main()
{
int n = 3;
struct rectangle box1 =
{
.width = 3,
.height = 4,
.arr1 = (int*) malloc( n * sizeof(int)),
.arr2 = (int*) malloc( n * sizeof(int))
};
}
However, I keep getting warning: initialization from int to int* makes integer from pointer without a cast [-Wint-conversion].
array is a slightly misleading name. For a dynamically allocated array of pointers, malloc will return a pointer to a block of memory. You need to use Chess* and not Chess[] to hold the pointer to your array.
Chess *array = malloc(size * sizeof(Chess));
array[i] = NULL;
and perhaps later:
/* create new struct chess */
array[i] = malloc(sizeof(struct chess));
/* set up its members */
array[i]->size = 0;
/* etc. */
There's a lot of typedef going on here. Personally I'm against "hiding the asterisk", i.e. typedef:ing pointer types into something that doesn't look like a pointer. In C, pointers are quite important and really affect the code, there's a lot of difference between foo and foo *.
Many of the answers are also confused about this, I think.
Your allocation of an array of Chess values, which are pointers to values of type chess (again, a very confusing nomenclature that I really can't recommend) should be like this:
Chess *array = malloc(n * sizeof *array);
Then, you need to initialize the actual instances, by looping:
for(i = 0; i < n; ++i)
array[i] = NULL;
This assumes you don't want to allocate any memory for the instances, you just want an array of pointers with all pointers initially pointing at nothing.
If you wanted to allocate space, the simplest form would be:
for(i = 0; i < n; ++i)
array[i] = malloc(sizeof *array[i]);
See how the sizeof usage is 100% consistent, and never starts to mention explicit types. Use the type information inherent in your variables, and let the compiler worry about which type is which. Don't repeat yourself.
Of course, the above does a needlessly large amount of calls to malloc(); depending on usage patterns it might be possible to do all of the above with just one call to malloc(), after computing the total size needed. Then you'd still need to go through and initialize the array[i] pointers to point into the large block, of course.
struct key* PrevKeys= malloc(345000*sizeof(struct key));
struct key* ActivityKeys= malloc(345000*sizeof(struct key));
struct key* CurKeys= malloc(345000*sizeof(struct key));
You're trying to assign the result of malloc, which is a pointer, to a struct, which is not possible. You have to declare them as pointers:
struct key *PrevKeys = malloc(345000 * sizeof(struct key));
...
and don't forget to free the memory:
free(PrevKeys);
If you're still getting errors, try to allocate just 10 elements, and if it works, you can be sure 345000 elements is too much.
Also, I'd prefer to not use sizeof(struct key) but sizeof(*PrevKeys) since it will always return the right size for PrevKeys, even if you change the type of PrevKeys.
How should i free the allocated memory that was used after calling malloc?
Consider below example,
struct datastore1 *obj1 = malloc(sizeof(struct datastore1));
free(obj1);
Here obj1 is pointing to the block of memory of size same as size of datastore1 in order to free you need to send the address which is allocated by malloc.

likewise,
struct datastore1 *obj2 = malloc(3 * sizeof(struct datastore1));
free(obj2);
obj2 is pointing to a block of contiguous memory of size 3 * sizeof(datastore1) you need to pass the base address to free

Should i free each indexes individually?
NO, Since block of memory is allocated only once and you need to free exactly one time.
Let me extend it further,
struct datastore1 *obj3[3];
for(int i=0;i<3;i++)
obj3[i] = malloc(sizeof(struct datastore1));
for(int i=0;i<3;i++)
free(obj3[i]);
Here obj3 is array of pointer and each index is pointing to different part of memory and hence need to be freed individually.

Note: For simplicity I haven't considered return value from malloc. Null check has to be done on malloc return value.
1.
How should I free the allocated memory that was used after calling malloc?
I tried doing
free(dsdata)on the end of the program but I am not sure if it's the right way.
free(dsdata) is fine, since you allocated the whole space by just one call to malloc with:
struct datastore1 *dsdata = malloc(30 * sizeof(struct datastore1));
To cite the standard (C18), 7.22.3.4 - "The malloc function" (emphasize mine):
7.22.3.4 The malloc function
Synopsis
1
#include <stdlib.h> void* malloc(size_t size);Description
2 The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.
Returns
3 The malloc function returns either a null pointer or a pointer to the allocated space.
It is correct to use free(dsdata) because malloc allocated all of the required space at once and returned a pointer to the first structure variable of this array which is assigned to the pointer of dsdata.
The free() function "knows" that dsdata is a reference to the whole allocated space. You do not need to free each of the 30 structures of type struct datastore1 in memory individually.
2.
Should I free each indexes individually?
No, you do not need and even more important you should not do so; this would be Undefined Behavior:
Citation from the current standard (C18), 7.22.3.5/3 - "The free function" (emphasize mine):
Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
If your array is declared with [] then you cannot dynamically allocate it. The [] mean the array will be automatically or statically allocated.
To dynamically allocate some structs that are zeroed, you should do:
struct line *set = calloc(num_lines, sizeof *set);
With dynamic allocation, the array itself does not have a name, however using the pointer set which points to its first element, you can still access all the array members.
I'm not exactly clear on what you are asking about cache, but perhaps it is supposed to be:
struct line **cache = calloc(num_sets, sizeof *cache);
for (size_t i = 0; i < num_sets; ++i)
cache[i] = calloc(num_lines, sizeof *cache[i]);
Please don't use pointer typedefs, they make the code hard to read. You can typedef struct line Line; if you want. And it doesn't really matter whether you do calloc(N, size) or malloc(N * size).
Then you can access those arrays using [] notation, e.g. cache[3][5].tag = 7;
L cache;
var = (L)malloc(n * sizeof(cache[0]));
Your problem is the way you declared the struct it should be
Copystruct data
{
int *ref;
int *port;
char data[MAX_STRING];
};
and then you do
Copystruct data *p_valid;
p_valid = malloc(sizeof(struct data));
another thing is
Copyp_valid->data = malloc(sizeof(STRINGMAX));
is wrong because data is not a pointer. And sizeof(STRINGMAX) is wrong too, since STRINGMAX seems to be a macro and hence it will expand to it's value say if you have #define STRINGMAX 4 then it would expand to sizeof(4).
CopyYour definition of the struct:
struct data {
int *ref;
int *port;
char data[MAX_STRING];
}temp, valid, invalid;
should be more like this:
struct data
{
int *ref;
int *port;
char data[MAX_STRING];
};
then define the arrays similar to this:
struct data temp;
struct data* valid = NULL;
struct data* invalid = NULL;
int currentValidSize = 0;
int currentInvalidSize = 0;
struct data * validTemp = NULL;
struct data * invalidTemp = NULL;
then, each time the code needs room for (another) instance of a struct
struct data *validTemp = realloc(valid, (currentValidSize+1)* sizeof(data) );
if( NULL == validTemp )
{ // realloc failed
perrof( "realloc failed" );
// free everything, close files, etc here probably be writing a sub function
// and calling it here.
// a sub function that:
// that walks the valid and invalid arrays,
// first free'ing any malloc'd fields
// then finally free'ing the whole array
exit( EXIT_FAILURE );
}
// implied else, realloc successful
// update array size counter
currentValidSize++;
// update ptr to valid array of structs
valid = validTemp;
validTemp = NULL;
similar for adding an entry to the invalid array of structs
then update the valid array of structs from temp as:
(note the '-1' in the offset into valid[])
memcpy( &valid[currentValidSize-1], &temp, sizeof data );
// Note you will also have to perform a 'deep' copy of any areas
// that were malloc'd within the 'temp' struct