You are trying to allocate a array with the size of the pointer to the date struct instead of the actual size of the date struct.
Change date* to date:
array = malloc(size*sizeof(date));
Furthermore you don't need to allocate the day and year variables, because the malloc allocates them for you.
for (i=0; i<size; i++)
{
array[i].month = calloc(MAX_MONTH_STR,sizeof(char));
array[i].day = 0;
array[i].year = 0;
}
Answer from user1350184 on Stack Overflowc - How to allocate memory and dereference an array of arrays within a struct? - Stack Overflow
c - Need help allocating memory for an struct array of arrays - Stack Overflow
c - How do I allocate memory for a struct with an array? - Stack Overflow
Correct way to allocate memory for struct with variable struct array?
Hi all! I am very new to C but am familiar with Python & Go quite a bit. Memory allocation is a new concept to me, but I want to start with best practices.
Lets say I want to create a struct that has some members, where one of them happens to be a pointer which I will size dynamically as an array.
Here is what I am doing in my init_my_struct(int n) function. I want to understand if I am doing something that is bad practice here
#include <stdlib.h>
#include <stdio.h>
struct my_struct {
int n;
int *my_arr; // this will be dynamically grown based on user arg
};
struct my_struct * init_my_struct(int n)
{
// allocate memory for one struct
struct my_struct *ms = malloc(sizeof(struct my_struct));
// use -> syntax since ms is a pointer
ms->n = n;
ms->my_arr = malloc(sizeof(int)*n);
return ms;
}
int main(int argc, char *argv[])
{
if (argc < 2) return 1;
int n = atoi(argv[1]);
// initialize the struct members
struct my_struct *ms = init_my_struct(n);
// check out contents of my struct
printf("my struct's n: %d\n", ms->n);
printf("my struct's my_arr: \n");
for (int i = 0; i < n; i++) {
printf("%d\n", ms->my_arr[i]);
}
free(ms); // clean up the memory
return 0;
}Any pointers or tips would be great! Thank you!
Hi,
currently I'm train my C skills (or get some in general, lol) and make a little training project: classical tic tac toe. I will "overcomplicate" the project on purpose with the intention to use many language skills as possible.
I will represent the "board" with this two structures:
struct game_board_bitmap {
char player: 2;
};
struct game_board {
unsigned int width;
unsigned int height;
unsigned int size;
struct game_board_bitmap* fields[];
};A classic board has a width and height of 3, so a size of 9. Every field should be represented with the struct game_board_bitmap and saved in a variable array in the struct game_board.
The purpose of the shown structure is to train the correct handling of malloc, free etc.
And this is also where I reach my limits. How do I create this nested structure correctly? I have tried it via the following way:
struct game_board* tictactoe_init_game_board(unsigned int const width, unsigned int const height) {
struct game_board* board = malloc(sizeof(struct game_board) + (width * height) * sizeof(struct game_board_bitmap));
// malloc test removed for space savings
board->width = width;
board->height = height;
board->size = width * height;
for (int i = 0; i < board->size; i++) {
board->fields[i]->player = 0; // 0 is default, field not assigned to any player
}
return board;
}
If I want access the board via printf("%c", board->fields[2]->player); the program crashes with a SIGSEGV. So I think I have done something wrong.
Can someone please explain to me what exactly I am doing wrong or how to do it right? Thank you! :)
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
}
There is no struct S, only S which is a typedef of anonymous structure.
Define struct S too:
typedef struct S {
char id;
struct S *children[SIZE];
}S;
Or:
typedef struct S S;
struct S {
char id;
S *children[SIZE];
};
And do avoid casting return of malloc in C:
arr[0].children[0] = malloc(sizeof(S));
For your first problem, you need to do:
#include <stdlib.h>
at the top of your program, in order to call malloc successfully.
The second problem (as also pointed out by others) is that struct S in your class definition refers to a different struct than S. In C, struct tags are in a different "namespace" than type names.
To allocate space for an array of nWords elements, use
wordArray = malloc(nWords * sizeof(*WordInfo));
- Cast malloc as the type you're returning.
- Remove subscript for the pointer.
Your objective is to allocate memory to hold the array and then set the pointer to it. One problem you'd have doing what you were doing is, if you you try to save the address malloc returns in a specific 'slot' of an array you haven't even created yet you will get an access error because wordArray[n] doesn't refer to any memory yet.
wordArray is pointer type variable you're trying to make point to the memory you allocate.
wordArray = (WordInfo *)malloc(sizeof(WordInfo));
Then you can access wordArray with subscripts.
E.g. wordArray[n]
In C pointers can be accessed via subscripts and arrays can be referenced with pointers. They are different representations and syntaxes for the pretty much the same thing.
When you use realloc(), you must give the new size instead of the number of bytes to add. So:
temp_struct = (struct st_temp **) realloc (temp_struct, 30 * sizeof(struct st_temp*));
30 is, of course, your original 20 plus 10 more. The realloc() function takes care of copying the original data to a new location if it needs to move the memory block.
Then, adding the extra 10 elements would be something like (starting at index 20, not 0):
for (j = 20; j < 30; j++) {
temp_struct[j]->prod = "some extra values";
}
To avoid memory leaks, we need to handle reallocating with care (more on that later). The realloc function:
void *realloc(void *ptr, size_t size), where
ptr = the pointer to the original (malloc'ed) memory block, and
size = the new size of the memory block (in bytes).
realloc returns the new location of the dynamically allocated memory block (which may have changed) - or NULL if the re-allocation failed! If it returns NULL, the original memory stays unchanged, so you must always use a temporary variable for the return value of realloc.
An example will clarify this a bit (points of interest: realloc syntax is similar to malloc's (no need for extra casts etc.) and, after realloc, you need to produce the same steps for the new objects as you did after malloc):
struct st_temp **temp_struct;
temp_struct = malloc(20 * sizeof *temp_struct);
if (temp_struct == NULL) { /* handle failed malloc */ }
for (int i = 0; i < 20; ++i) {
temp_struct[i] = malloc(sizeof *temp_struct[i]);
temp_struct[i]->prod = "foo";
}
// We need more space ... remember to use a temporary variable
struct st_temp **tmp;
tmp = realloc(temp_struct, 30 * sizeof *temp_struct);
if (tmp == NULL) {
// handle failed realloc, temp_struct is unchanged
} else {
// everything went ok, update the original pointer (temp_struct)
temp_struct = tmp;
}
for (int i = 20; i < 30; ++i) { // notice the indexing, [20..30)
// NOTICE: the realloc allocated more space for pointers
// we still need to allocate space for each new object
temp_struct[i] = malloc(sizeof *temp_struct[i]);
temp_struct[i]->prod = "bar";
}
// temp_struct now "holds" 30 temp_struct objects
// ...
// and always do remember, in the end
for (int i = 0; i < 30; ++i)
free(temp_struct[i]);
free(temp_struct);
Do note, that this is not really an array of structs, but more an array of pointers to structs - or even an array of arrays of struct if you wish. In the last case, each sub-array would be of length 1 (since we only allocate space for one struct).