Home > Software design >  malloc a "member" of struct v.s. whole struct when struct is quite simple
malloc a "member" of struct v.s. whole struct when struct is quite simple

Time:09-24

I have searched on this site the topics about malloc on structs. However, I have a slightly problem. Is that malloc on the element of a struct different from malloc on the whole struct, especially when that struct is quite simple, that is, only a member that is exactly what we all want to allocate? To be clear, see the code corresponding to student and student2 structs below.

struct student {
    int* majorScore;
};

struct student2 {
    int majorScore[3];
};


int main()
{
    struct student john;
    john.majorScore = (int*) malloc(sizeof(int) * 3);
    john.majorScore[0] = 50;
    john.majorScore[1] = 27;
    john.majorScore[2] = 56;
 
    struct student2* amy= (struct student2*)malloc(sizeof(struct student2));
    amy->majorScore[0] = 50;
    amy->majorScore[1] = 27;
    amy->majorScore[2] = 56;


    return 0;
}

Are they different in memory level? If yes, what is the difference? If no, which is perhaps better in terms of a good programming style?

CodePudding user response:

First, you dynamically allocate one struct, but not the other. So you're comparing apples to oranges.


Statically-allocated structs:

struct student john;
john.majorScore = malloc(sizeof(int) * 3);
john.majorScore[0] = 50;
john.majorScore[1] = 27;
john.majorScore[2] = 56;

struct student2 amy;
amy.majorScore[0] = 50;
amy.majorScore[1] = 27;
amy.majorScore[2] = 56;
struct student john
 ------------ ----------        ---------- 
| majorScore |         ------->|       50 |
 ------------ ----------        ---------- 
| [padding]  |          |      |       27 |
 ------------ ----------        ---------- 
                               |       56 |
                                ---------- 

struct student2 amy
 ------------ ---------- 
| majorScore |       50 |
|             ---------- 
|            |       27 |
|             ---------- 
|            |       56 |
 ------------ ---------- 
| [padding]  |          |
 ------------ ---------- 

struct student uses more memory because it has an extra value (the pointer), and it has the overhead of two memory blocks instead of one.

struct student2 always has memory for exactly three scores, even if you need fewer. And it can't possibly accommodate more than 3.


Dynamically-allocated structs:

struct student *john = malloc(sizeof(struct student));
john->majorScore = malloc(sizeof(int) * 3);
john->majorScore[0] = 50;
john->majorScore[1] = 27;
john->majorScore[2] = 56;

struct student2 *amy = malloc(sizeof(struct student2));
amy->majorScore[0] = 50;
amy->majorScore[1] = 27;
amy->majorScore[2] = 56;
struct student *john
 ----------        ------------ ----------        ---------- 
|         ------->| majorScore |         ------->|       50 |
 ----------        ------------ ----------        ---------- 
                  | [padding]  |          |      |       27 |
                   ------------ ----------        ---------- 
                                                 |       56 |
                                                  ---------- 

struct student2 *amy
 ----------        ------------ ---------- 
|         ------->| majorScore |       50 |
 ----------       |             ---------- 
                  |            |       27 |
                  |             ---------- 
                  |            |       56 |
                   ------------ ---------- 
                  | [padding]  |          |
                   ------------ ---------- 

Same analysis as above.

CodePudding user response:

Is malloc on a struct simple? Sure, it certainly is. Although you don't need malloc whatsoever for your struct student2 definition, and I'd argue that just using the struct directly and avoiding malloc is MUCH simpler. It's important to note that malloc on a struct will only allocate the size of the struct itself, not the size of dynamic data pointed to by pointers within the struct. What you are comparing is two different structs with very different implementations, so it isn't really fair to say "which one is better" because it largely depends on your actual use cases.

For clarity, let's say you did struct student* john = malloc(sizeof(struct student)). If you allocate storage for a struct like this, you still need to allocate memory for majorScore since it the initial malloc only allocates room for the int * and nothing past that. As you can see, that complicates things even more.

So the conclusion is, in general you only want to use malloc for dynamic memory allocation in circumstances where you may not know the size of data at compile time. There is no reason to introduce complexity (and likely bugs/leaks) through malloc in the examples you have provided. The utility of using malloc in your example for struct student is that majorScore can be an array of any size, not just 3 as in the struct student2 definition.

  • Related