C and zero-sized arrays - what is the standard?

Thu Sep 18 13:18:00 GMT 2003

```Hi Alex,

>Is there a portable way to do this? What is the right form according to the standards?

I'm not exactly sure what the standard (ISO 9899) says about zero sized arrays at the end of a struct, or non-specified sized arrays at the end of a struct.  I'm willing to wager a guess that they are invalid.

Usually this technique is used for "stretchy buffers".

There are several approaches to the stretchy buffer problem:
+ Use an unspecified array size at the end of the struct. (non-ISO 9899)
+ Use an array size of ZERO at the end of the struct. (non-ISO 9899)
+ Use an array size of ONE at the end of the struct.
+ Use an array size of the LARGEST possible buffer size at the end of the struct.

I'm in the last camp.  For safety reasons, it is best to err on the size of "buffers specified too big" rather than "buffers specified too small" (causing overruns, terror, raining cats-n-dogs, plagues of locusts).  However, note, all of these techniques are ISO 9899 suspect.

#define MAX_BUF 1024
struct MyBuf
{
int length;
int array[MAX_BUF];
};
extern int calc_buf_size(int n_elements);

When allocating a stretchy buffer, using the last convention, you'd do something like:
MyBuf* buf = malloc(calc_buf_size(3));

And your "calc_buf_size" routine does the math, ala:
int calc_buf_size(int n)
{
return sizeof(MyBuf) - ((MAX_BUF - n) * sizeof(int));
}

I like to isolate the buf size calculation, so that it's easier to modify in one place than if the calculation were strewn throughout the code.

When allocating a .data section (i.e., a global) or a stack based MyBuf, it will consume the maximum buf size.  For embedded systems, that may be unacceptable.  However, having the data array that over-runs the bounds of the array is suspect and I would expect its behavior to be platform (OS + compiler) dependent.

(Hmmm, I don't think I really answered your question.  I more-or-less danced around it.  Sorry.  Let me try again.)

>Is there a portable way to do this?

Yes, but it'll be very ugly, a lot more work (for little-to-no gain), is at variance to how stretchy buffers are normally done by embedded systems programmers, and a maintenance nightmare.

So I won't bother explaining too much.  Let me just say:  it involves having explicitly sized structures for every size that you are interested in.

In the pre-Darwin days of Mac OS, they had str15, str63, str255 (and others) for Pascal style strings, for example.

>What is the right form according to the standards?

There is no "right form".  Using stretchy buffers is just something not supported by the language proper, and every time they're done it's ad hoc and slightly-to-greatly suspect.

I recommend the "largest specified buffer or smaller" technique.  Others swear by the "buffer-size-one plus" technique.  Either way, portability is a concern -- and can be extremely frustrating.

--Eljay

PS:  I'm not familiar with the new "dynamic" array facility of C99.  So some of my advice may have been superceded by new language facilities.

```