jeremy radcliff jeremy radcliff - 4 years ago 168
C Question

Why does node* root = malloc(sizeof(int)) allocate 16 bytes of memory instead of 4?

I'm messing around with Linked List type data structures to get better with pointers and structs in C, and I don't understand this.

I thought that

malloc
returned the address of the first block of memory of size
sizeof
to the pointer.

In this case, my
node struct
looks like this and is 16 bytes:

typedef struct node{
int index;
struct node* next;
}node;


I would expect that if I try to do this:
node* root = malloc(sizeof(int))


malloc
would allocate only a block of 4 bytes and return the address of that block to the pointer
node
.

However, I'm still able to assign a value to index and get root to point to a next node, as such:

root->index = 0;
root->next = malloc(sizeof(node));


And the weirdest part is that if I try to run:
printf("size of pointer root: %lu \n", sizeof(*root));


I get
size of pointer root: 16
, when I clearly expected to see
4
.

What's going on?

EDIT: I just tried
malloc(sizeof(char))
and it still tells me that
*root
is 16 bytes.

Answer Source

There is a few things going on here, plus one more that probably isn't a problem in this example but is a problem in general.

1) int isn't guaranteed to be 4 bytes, although in most C compiler implementations they are. I would double check sizeof(int) to see what you get.

2) node* root = malloc(sizeof(int)) is likely to cause all sorts of problems, because sizeof(struct node) is not the same as an int. As soon as you try to access root->next, you have undefined behavior.

3) sizeof(struct node) is not just an int, it is an int and a pointer. Pointers are (as far as I know, someone quote the standard if not) the same size throughout a program depending on how it was compiled (32-bit vs 64-bit, for example). You can easily check this on your compiler with sizeof(void*). It should be the same as sizeof(int*) or sizeof(double*) or any other pointer type.

4) Your struct should be sizeof(int) + sizeof(node*), but isn't guaranteed to be. For example, say I have this struct:

struct Example
{
  char c;
  int i;
  double d;
};

You'd expect its size to be sizeof(char) + sizeof(int) + sizeof(double), which is 1 + 4 + 8 = 13 on my compiler, but in practice it won't be. Compilers can "align" members internally to match the underlying instruction architecture, which generally will increase the structs size. The tradeoff is that they can access data more quickly. This is not standardized and varies from one compiler to another, or even different versions of the same compiler with different settings. You can learn more about it here.

5) Your line printf("size of pointer root: %lu \n", sizeof(*root)) is not the size of the pointer to root, it is the size of the struct root. This leads me to believe that you are compiling this as 64-bit code, so sizeof(int) is 4, and sizeof(void*) is 8, and they are being aligned to match the system word (8 bytes), although I can't be positive without seeing your compiler, system, and settings. If you want to know the size of the pointer to root, you need to do sizeof(node*) or sizeof(root). You dereference the pointer in your version, so it is the equivalent of saying sizeof(node)

Bottom line, is that the weirdness you are experiencing is undefined behavior. You aren't going to find a concrete answer, and just because you think you find a pattern in the behavior doesn't mean you should use it (unless you want impossible to find bugs later that make you miserable).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download