Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array of size 0 at the end of struct [duplicate]

My professor of a systems programming course I'm taking told us today to define a struct with a zero-length array at the end:

struct array{     size_t size;     int data[0]; };  typedef struct array array; 

This is a useful struct to define or initialize an array with a variable, i.e., something as follows:

array *array_new(size_t size){     array* a = malloc(sizeof(array) + size * sizeof(int));      if(a){         a->size = size;     }      return a; } 

That is, using malloc(), we also allocate memory for the array of size zero. This is completely new for me, and it's seems odd, because, from my understanding, structs do not have their elements necessarily in continuous locations.

Why does the code in array_new allocate memory to data[0]? Why would it be legal to access then, say

array * a = array_new(3); a->data[1] = 12; 

?

From what he told us, it seems that an array defined as length zero at the end of a struct is ensured to come immediately after the last element of the struct, but this seems strange, because, again, from my understanding, structs could have padding.

I've also seen around that this is just a feature of gcc and not defined by any standard. Is this true?

like image 296
nbro Avatar asked Apr 12 '16 15:04

nbro


People also ask

Can I declare an array of size 0?

The alignment of a zero-length array is the same as the alignment of its elements. Declaring zero-length arrays in other contexts, including as interior members of structure objects or as non-member objects, is discouraged.

Why do some structures end with an array of size 1?

Some Windows structures are variable-sized, beginning with a fixed header, followed by a variable-sized array. When these structures are declared, they often declare an array of size 1 where the variable-sized array should be.

Can we create zero length array Java?

e.No, it is not possible to create arrays of length zero in Java.


2 Answers

Currently, there exists a standard feature, as mentioned in C11, chapter §6.7.2.1, called flexible array member.

Quoting the standard,

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. [...]

The syntax should be

struct s { int n; double d[]; }; 

where the last element is incomplete type, (no array dimensions, not even 0).

So, your code should better look like

struct array{     size_t size;     int data[ ]; }; 

to be standard-conforming.

Now, coming to your example, of a 0-sized array, this was a legacy way ("struct hack") of achieving the same. Before C99, GCC supported this as an extension to emulate flexible array member functionality.

like image 184
Sourav Ghosh Avatar answered Oct 08 '22 18:10

Sourav Ghosh


Your professor is confused. They should go read what happens if I define a zero size array. This is a non-standard GCC extension; it is not valid C and not something they should teach students to use (*).

Instead, use standard C flexible array member. Unlike your zero-size array, it will actually work, portably:

struct array{     size_t size;     int data[]; }; 

Flexible array members are guaranteed to count as zero when you use sizeof on the struct, allowing you to do things like:

malloc(sizeof(array) + sizeof(int[size])); 

(*) Back in the 90s people used an unsafe exploit to add data after structs, known as the "struct hack". To provide a safe way to extend a struct, GCC implemented the zero-size array feature as a non-standard extension. It became obsolete in 1999 when the C standard finally provided a better way to do this.

like image 37
Lundin Avatar answered Oct 08 '22 19:10

Lundin