Reputation: 7
I'm brushing up on some C programming, and trying to understand why I cannot print a data item from a structure (struct) after dynamically allocating memory to for structure.
I tried printing the data items in the struct to see what values I get but my code does not compile, and I get an error.
#include <stdio.h>
#include <stdlib.h>
typedef struct Collection {
int age;
char date[20];
char name[20];
} Collection;
int main(void) {
int i;
int n = 10;
Collection **dataCollection;
dataCollection = malloc(sizeof(Collection*)*n);
dataCollection->age = 20;
for(i = 0; i < n; i++) {
dataCollection[i] = malloc(sizeof(Collection)*n);
printf("Data collection item: %d\n", dataCollection->age);
}
for(i = 0; i < n; i++)
free(dataCollection[i]);
free(dataCollection);
return 0;
}
I get the following errors:
practice1019.c:18:20: error: member reference base type 'Collection *' (aka 'struct Collection *')
is not a structure or union
dataCollection->age = 20;
~~~~~~~~~~~~~~^ ~~~
practice1019.c:23:56: error: member reference base type 'Collection *' (aka 'struct Collection *')
is not a structure or union
printf("Data collection item: %d\n", dataCollection->age);
Upvotes: 0
Views: 2137
Reputation: 84607
Continuing from the comment, you cannot assign dataCollection->age = 20;
after merely allocating a block of memory sufficient to hole 10
pointers-to Collection
. You have allocated memory for the pointers, but not storage for the stucts themselves.
Additionally, you must validate every allocation, e.g.
dataCollection = malloc(sizeof(Collection*)*n);
if (!dataCollection) { /* validate EVERY allocation */
perror ("malloc-dataCollection");
return 1;
}
Now, before you can assign a value to a member of any struct, you must allocate a block of memory to hold the struct and then assign the starting address for that block to one of the pointers you have just allocated, e.g.
for (i = 0; i < n; i++) {
dataCollection[i] = malloc(sizeof(Collection));
if (!dataCollection[i]) { /* ditto */
perror ("malloc-dataCollection[i]");
return 1;
}
(note: above there is no * n
after Collection
in sizeof(Collection)
-- or you will over-allocate by a factor of 10
on struct storage...)
Now, you have storage for a struct and you can make use of the members (age
below)
dataCollection[i]->age = i + 20;
printf("Data collection[%d] age: %d\n", i, dataCollection[i]->age);
}
Good job on the free
of each of the structs and then the pointers. Putting it altogether, you could do:
#include <stdio.h>
#include <stdlib.h>
typedef struct Collection {
int age;
char date;
char name;
} Collection;
int main (void) {
int i;
int n = 10;
Collection **dataCollection;
dataCollection = malloc(sizeof(Collection*)*n);
if (!dataCollection) { /* validate EVERY allocation */
perror ("malloc-dataCollection");
return 1;
}
for (i = 0; i < n; i++) {
dataCollection[i] = malloc(sizeof(Collection));
if (!dataCollection[i]) { /* ditto */
perror ("malloc-dataCollection[i]");
return 1;
}
dataCollection[i]->age = i + 20;
printf("Data collection[%d] age: %d\n", i, dataCollection[i]->age);
}
for(i = 0; i < n; i++)
free(dataCollection[i]);
free(dataCollection);
}
Example Use/Output
$ ./bin/datacollection
Data collection[0] age: 20
Data collection[1] age: 21
Data collection[2] age: 22
Data collection[3] age: 23
Data collection[4] age: 24
Data collection[5] age: 25
Data collection[6] age: 26
Data collection[7] age: 27
Data collection[8] age: 28
Data collection[9] age: 29
Look things over and let me know if you have questions.
Upvotes: 1