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.
精彩评论