开发者

Which is correct when allocating memory for a struct in C

Assuming we have a simple struct like:

typedef struct开发者_JAVA百科
{
    int d1;
    int d2;
    float f1;
}Type;

Which is the correct when allocate memory for a new instance of it:

This:

// sizeof *t == sizeof(Type) ( gcc prints 12 bytes)
Type *t = malloc(sizeof *t); 

or:

// sizeof pointer always == 4 (in my case also on gcc)
Type *t = malloc(sizeof(t)); 

Which is the correct?


This is the correct way:

Type *t = malloc(sizeof *t); 

Why this is correct?

Because you correctly allocate a size big enough to hold a structure. *t points to a type Type.


This is incorrect way:

Type *t = malloc(sizeof(t)); 

Why this is Incorrect?

sizeof(t) returns size of pointer and not the actual type(i.e: not the size of the structure).
What you need to allocate is size big enough to hold a structure not size equal to pointer to structure.

Note that, Size of an pointer pointing to Any type is same on an system.


Why is the first approach better?
With the first approach, when you change Type, the malloc automatically changes size to be the correct value, you do not have to do that explicitly unlike other ways.

Also, the important part of writing an malloc call is finding the correct size that needs to be passed. The best way to do this is not to look anywhere (because that is when we make the mistake) but only at the left hand side of this malloc statement. Since, it is t in this case therefore the correct size will be sizeof(*t).

How to standardize use of malloc?

With above mentioned correct approach there is one problem say, if we want to malloc say 30 elements. Then our malloc expression becomes:

t = (T *) malloc(30 * sizeof (*T));

This is not the preferred way to write a malloc expression, because one can make a mistake which entering the number 30 in the malloc parameter. What we would like- irrespective of the number of elements required the malloc parameter should always be the standard sizeof(*x) or something similar.

So here is an approach with an example:

Suppose we have a pointer p, pointing to a single dimensional array of size 20, whose each element is struct node. The declaration will be:

 struct node (*p) [20];   

Now if we wish to malloc 20 elements of stuct node, and wish that pointer p should hold the return address of malloc then we have

p = (data-type of p) malloc (size of 20 elements of struct node); 

To find the data type of p, for casting we just make the variable name disappear or replace p with a blank. So we now have

p = (struct node (*)[20] ) malloc(size of 20 elements of struct node);

We can't go very wrong over here because the compiler will complain if we are wrong. Finally the size! We just do the standard way we have described, that is

p =  (struct node (*)[20] ) malloc(sizeof (*p));

And we are done!


Type *t = malloc(sizeof *t); 

This is the correct way to allocate the amount of memory needed for a new instance.

Type *t = malloc(sizeof (t)); 

This will only allocate enough storage for a pointer, not an instance.


sizeof(*t), because t is of type Type* so that *t points to something of type Type.

But I would suggest to use this instead, because it's more readable and less error prone:

Type *t = malloc(sizeof(Type));


this one:

Type *t = malloc(sizeof(*t));

you allocate memory for the struct, not for a pointer.


The first is correct. Second will not allocate enough memory, because t has the size of a pointer. Better yet is

Type *t = malloc(sizeof(Type));


Preferably: Type * t = malloc(sizeof(Type));

Arguably, sizeof *t works as well and allows you to change the actual type of *t without requiring you to modify two separate locations, but using the type rather than an expression in the initial allocation feels more readable and expressive... that's subjective, though. If you you want to keep your options open to change the type, I'd personally prefer factoring that change into the typedef rather than the variable declaration/initialization.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜