Array of zero length

Viewed 30321

I am working on refactoring some old code and have found few structs containing zero length arrays (below). Warnings depressed by pragma, of course, but I've failed to create by "new" structures containing such structures (error 2233). Array 'byData' used as pointer, but why not to use pointer instead? or array of length 1? And of course, no comments were added to make me enjoy the process... Any causes to use such thing? Any advice in refactoring those?

struct someData
{
   int nData;
   BYTE byData[0];
}

NB It's C++, Windows XP, VS 2003

5 Answers

Yes this is a C-Hack.
To create an array of any length:

struct someData* mallocSomeData(int size)
{
    struct someData*  result = (struct someData*)malloc(sizeof(struct someData) + size * sizeof(BYTE));
    if (result)
    {    result->nData = size;
    }
    return result;
}

Now you have an object of someData with an array of a specified length.

There are, unfortunately, several reasons why you would declare a zero length array at the end of a structure. It essentially gives you the ability to have a variable length structure returned from an API.

Raymond Chen did an excellent blog post on the subject. I suggest you take a look at this post because it likely contains the answer you want.

Note in his post, it deals with arrays of size 1 instead of 0. This is the case because zero length arrays are a more recent entry into the standards. His post should still apply to your problem.

http://blogs.msdn.com/oldnewthing/archive/2004/08/26/220873.aspx

EDIT

Note: Even though Raymond's post says 0 length arrays are legal in C99 they are in fact still not legal in C99. Instead of a 0 length array here you should be using a length 1 array

This is an old C hack to allow a flexible sized arrays.

In C99 standard this is not neccessary as it supports the arr[] syntax.

It's worth pointing out IMO the best way to do the size calculation, which is used in the Raymond Chen article linked above.

struct foo
{
    size_t count;
    int data[1];
}

size_t foo_size_from_count(size_t count)
{
    return offsetof(foo, data[count]);
}

The offset of the first entry off the end of desired allocation, is also the size of the desired allocation. IMO it's an extremely elegant way of doing the size calculation. It does not matter what the element type of the variable size array is. The offsetof (or FIELD_OFFSET or UFIELD_OFFSET in Windows) is always written the same way. No sizeof() expressions to accidentally mess up.

Related