Sunday, February 17, 2008

0 is a perfectly valid input to the array form of new expression. What is the use of it, you may ask. No use as far as the array is concerned. What use is an array if it does not have any members? What can you possibly do with it? Nothing! Right, you cannot do anything with it but the statement above being valid is atleast a little bit helpful.

Since the zero size member is in there, there are few restrictions as well. You cannot create an array of the test struct. You can mimic that though like this:

//create an array of length 10 of test pointers test * ptr[10]; //set each of the pointers to individual elements created as above

Generally, you would be better off keeping a pointer member but it is worth noting the presence of such an extension. See for details : Unsized arrays.

The rationale as per msdn is saving the runtime pointer dereferences and that is not specific to C. How big that overhead is, with respect to the application in order to make a choice to this extension, is a different story altogether. You could even implement std::vector<T> using this extension rather than having a pointer to type T! That is, std::vector<T> implementation with VC++ might use this extension but they don't do so. :-)

It's a useful fature, but if you're talking about C++ (not C), then it's not portable because ISO C++ forbids zero-size arrays. I know that almost all implementations supoprt that but it's still not in standard even in c++0x.

Another interesting property is that in g++ this seems to be the only way to create a member that really has zero size. (sizeof an empty struct always seems to yield 1). If however a struct contains a zero-sized array, the size of the struct will also be zero.

So say you are writing a templated class and the user should be able to provide an allocator (or some other thingy).So that would look like this:

templatestruct Foo { int x, y; AllocRefT allocator;};

Sometimes the user might have multiple allocators in use, in which case the allocator reference member is worth the effort, but often enough there will be only a single allocator object.

In the latter case you can save the space for the allocator reference by defining AllocRefT like this

struct AllocRefT { int zeroer[0]; // makes struct size 0

static Something operator->(...); static Something operator*(...);};

this way your references take up no space although you can still call static methods on them.

Note (as said earlier) that this is not portable. Also it breaks in certain situations where the compiler will calculate the address of a member following a zero-sized member (so its better to have this as last member in the struct always).To make this clear: I don't know if this behaviour of g++ is documented anywere or if it could be considered a bug of some sort. However I totally love it because you can really do awesome things with it :)

I had a stackoverflow question on this: http://stackoverflow.com/questions/8271673/can-there-be-a-c-type-that-takes-0-bytes. They said that zero length arrays are illegal by the standard, but are a common extension. I used them under GCC, so they must be relatively common if GCC and VC++ support them.