Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we use zero length array instead of pointers?

It's said that zero length array is for variable length structure, which I can understand. But what puzzle me is why we don't simply use a pointer, we can dereference and allocate a different size structure in the same way.

EDIT - Added example from comments

Assuming:

struct p
{
    char ch;
    int *arr;
};

We can use this:

struct p *p = malloc(sizeof(*p) + (sizeof(int) * n));

p->arr = (struct p*)(p + 1);

To get a contiguous chunk of memory. However, I seemed to forget the space p->arr occupies and it seems to be a disparate thing from the zero size array method.

like image 945
dspjm Avatar asked Jun 03 '13 10:06

dspjm


2 Answers

If you use a pointer, the structure would no longer be of variable length: it will have fixed length, but its data will be stored in a different place.

The idea behind zero-length arrays* is to store the data of the array "in line" with the rest of the data in the structure, so that the array's data follows the structure's data in memory. Pointer to a separately allocated region of memory does not let you do that.


* Such arrays are also known as flexible arrays; in C99 you declare them as element_type flexArray[] instead of element_type flexArray[0], i.e. you drop zero.
like image 102
Sergey Kalinichenko Avatar answered Sep 17 '22 17:09

Sergey Kalinichenko


The pointer isn't really needed, so it costs space for no benefit. Also, it might imply another level of indirection, which also isn't really needed.

Compare these example declarations, for a dynamic integer array:

typedef struct {
  size_t length;
  int    data[0];
} IntArray1;

and:

typedef struct {
  size_t length;
  int    *data;
} IntArray2;

Basically, the pointer expresses "the first element of the array is at this address, which can be anything" which is more generic than is typically needed. The desired model is "the first element of the array is right here, but I don't know how large the array is".

Of course, the second form makes it possible to grow the array without risking that the "base" address (the address of the IntArray2 structure itself) changes, which can be really neat. You can't do that with IntArray1, since you need to allocate the base structure and the integer data elements together. Trade-offs, trade-offs ...

like image 27
unwind Avatar answered Sep 18 '22 17:09

unwind