Zero-length arrays

Earlier this morning, my classmate and friend Raj (who btw is a hardcore open-source gnu/linux guy) sent an email to our class mailing list commenting on how he found a struct in some code he was working on that had a zero-length array member, and how he thought that was weird. What he was talking about was the old C-style flexible arrays, where you could legally define a zero-length array as the last member of a struct definition. The idea is to use this zero-length array as a reference to variable length data that’d be stored using the struct. If you are wondering why a pointer is not used, the size of a pointer would be non-zero, whereas the size of a zero-length array is guaranteed to be zero.

The GNU C compiler apparently still permits this, and the VC++ 2005 compiler permits it too, though it issues a Level-4 warning if it’s C code, and a Level-2 warning if it’s C++ code. Here’s some sample code that shows how to use a zero-length array.

struct D
{
    char y[10];
};

struct E
{
    char a[10];
    D d[0]; // Zero length array
};


int _tmain()
{
    E* e = (E*)malloc(sizeof(E) + sizeof(D) * 5);
    D* d = new D[5];
    memcpy(e->d,d,sizeof(D) * 5);
    delete d;
    free(e);
    return 0;
}
Posted in C++

11 thoughts on “Zero-length arrays

  1. Hey Kyle,

    It’s used when you want to have variable length data in your struct. So you cannot know before hand how many bytes you’d need.

  2. In C++, this isn’t quite as handy as it was with pure C. More often than not, one would now have a class with say a vector or deque do the work. The arguments for the ZLA to be more useful than using a pointer or similar, however, would be the same now:

    With both C and C++, you may find yourself in need of a structure of consecutive bytes, and wish for it to not take up more room than absolutely necessary. This could, for instance, be a structure sent as a raw packet over the wire to another program, which would restore it. Another example would be systems with a very high count of structs, where the 4 byte overhead of the pointer would mean several hundred MB of memory.

    The actual variable data could be just about anything, ranging from a set of integer options of unknown length, to a sequence of characters. Key points: you didn’t know how much data would be needed when you designed the struct interface, but you want the end amount to be as low as possible.

    See http://www.indev.no/ZLA.htm for a structural comparison between the pointer/zero-length array approaches.

  3. I think one of the most common uses for variable data in this manner is for storing data in a disk file.

    Since I can’t see the end of the line of what I am typing in here, I can’t elborate.

  4. hai im working as a lecturer in an engg college.. can u pls help me for creating a modeless dialog want the .
    actually i want the sequence of steps… this is very silly job for u..

  5. struct WaveFormatExt : public WAVEFORMATEX
    {
    char data[0];
    };

    then use it like:

    WaveFormatExt* pwfx = (WaveFormatExt*) new char[sizeof(WAVEFORMATEX) + /*say*/ 10];

    and initialize the normal WAVEFORMATEX data, and set cbSize = 10, and add the driver specific data in “data”.

    This way you know that all the data will be in one contiguous block. Not terribly useful under most circumstances, but when you need it, you really need it.

  6. While not directly related to ZLA, your example should have
    delete[] d;
    rather than
    delete d;

    – Wayne

  7. Well, the satement about zero-length “old C-style flexible arrays” is incorrect. I has never been legal to declare a zero-length array in neither C nor C++. Zero-length array declarations are always explicitly illegal in C/C++, regardless of context. The technique with a flexible-length array at the end of a struct is a well-known one, it is called “struct hack” and it uses an array of length 1 (one). One, not zero. Of course, in order to calculate the amount of memory for the struct instance, one has to take into account that one element of the array is already present in the ‘sizeof’ of the struct. But regardless, that’s the only semi-legal way to do it in C/C++. In the newest C standard – C99 – the “struct hack” has been fully legalized and in order to implement it one has to declare a size-less array at the end of the struct (i.e. use empty ‘[]’ in the array declaration). So, one again, in the older C compilers the “struct hack” is implemented by using an array of length 1, in the newer, C99 compiler it is implemented by using a size-less array declaration. And it is not legal, and it has never been legal to declare a zero-sized array in C/C++ for any purpose. Your compiler might let it slip through, but that would be nothing else than just a lousy compiler implementation.

Leave a reply to Kyle Cancel reply