Reputation: 97
This is my first post. I'm very confused with the C's pointer and its relation to struct. I've searched for more information but can't really conclude them. For example given this struct definition
typedef struct node
{
int info;
struct node *next;
}NODE;
Then what's the differences and effects of these four declarations;
1. NODE *node1 = malloc (sizeof(NODE));
2. NODE *node1 = (struct node *) malloc (sizeof(NODE));
3. NODE *node1 = (struct node *) malloc (sizeof(NODE *));
4. NODE *node1 = malloc (sizeof(NODE *));
Thanks in advance.
Upvotes: 3
Views: 199
Reputation: 8215
These are equivalent and allocate a block of memory the same size as a NODE struct.
1. NODE *node1 = malloc (sizeof(NODE));
2. NODE *node1 = (struct node *) malloc (sizeof(NODE));
These are just wrong
3. NODE *node1 = (struct node *) malloc (sizeof(NODE *));
4. NODE *node1 = malloc (sizeof(NODE *));
Line 3 allocates a memory block the size of a pointer to a NODE structure. The cast allows you to assign it without any errors being thrown, and possibly without warnings. But it's not what you want.
Line 4 does the same as line 3. malloc
returns a void *
which doesn't require casting, but a good static analyzer should give you a warning.
Either way, lines 3 & 4 are recipes for buffer overflows and undefined behavior.
Lines 3 and four would be correct if written thus:
NODE **ptr = malloc(sizeof(NODE *));
Upvotes: 6
Reputation: 22382
Given:
3) and 4) are not allocating enough memory for the struct, but only enough memory to hold the pointer to a struct (say 4 bytes on a 32-bit system) and then telling the compiler to treat that memory as if it was enough to occupy a NODE
1) is correct way to allocate enough memory for the structure (caveat other issues described below)
2) is bad practice because what you really mean is:
NODE *node1 = (NODE *) malloc(sizeof(NODE));
even though NODE
is typedef struct node
(2) says that you know that for sure.
Having said that,
All of them are bad practices for a reason explained later on below.
What you really want to do in practice is something like this:
Only use typedefs when you want to keep things really opaque about the inner structure (the way stdio does FILE) it's better practice to use struct foo bar;
in your declaration than typedef
ing the struct. Especially when the structure is exposed to other parts of the program.
typedef
is better used when you want to ensure that a type is uniformly interpreted on different architectures, e.g. the use of typedef unsigned long long uint64_t
vs typedef unsigned uint64_t
on 32-bit and 64-bit intel x86 cpus in stdint.h
struct node {
struct node *next;
size_t n_dlen;
void * n_data;
};
int main() {
struct node *node;
node = malloc(sizeof(*node));
}
Notice that I used sizeof(*node) instead of sizeof(struct node), because if I decide later on that node should be some other type say struct new_node *
then all i have to do is change the declaration and the sizeof(*node)
will still be okay.
Upvotes: 0
Reputation: 17668
// node1 is a pointer to (heap) memory block of size NODE
1. NODE *node1 = malloc (sizeof(NODE));
// same as 1. (but 1. is the preferred way)
2. NODE *node1 = (struct node *) malloc (sizeof(NODE));
// (Wrong) node1 is a pointer to (heap) memory block of size pointer to NODE (a pointer to _usually_ 4 bytes)
// but you cast it to pointer to NODE (a pointer to more than 4 bytes)
3. NODE *node1 = (struct node *) malloc (sizeof(NODE *));
// (Wrong) same as 3
4. NODE *node1 = malloc (sizeof(NODE *));
Stick with number 1. as it's the common way to allocate an object in the heap (dynamic allocation): Object *object = malloc(sizeof(Object))
. You can forget about 2. 3. 4. which complicate the issue and really not what you need.
Upvotes: 3