[comp.lang.c] Re^2: Zero Length Arrays

asd@cbnewsj.ATT.COM (adam.denton) (12/08/89)

In article <9895@cbnewsj.ATT.COM> gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
>[acrimonious stuff deleted...]
>
>Possible uses for zero-sized objects (notably arrays) have
>already been posted.

Yes, I have seen the uses for DECLARING a zero-sized array.  The issue
is a bit more subtle, though.  The point in question is the difference
between static and dynamic array sizing.  In C, arrays assume the size
of which they are declared at compile time.  In a language with dynamic
arrays (such as ALGOL), arrays are allocated at run time -- thus their
size need not be specified during compile time.

When we say
   struct str { some_declarations; <type> a[0]; } mama;
we want the structure type `struct str' to have a terminating array field
tagged `a' of zero length.  For any array, the only subscripts permitted are
   1) those that fall within the array, and
   2) the single subscript that falls ONE element past the end of the array.
If you believe this (which is true for ALL arrays in pANS, I think**),
then you will agree that if the above declaration is legal, then
   mama.a[0]
is legal, since the subscript [0] meets the criteria above for legality
(specifically, number 2 above).  Would you also agree that
  mama.a[1]
is not legal, since it does not meet either of the criteria above
(the subscript [1] is TWO past the end of the array) ??

-----
** If not, then I have royally goofed, and would appreciate being enlightened
   as to the exact wording of the `up to 1-past the end of the array'
   clause(s), wherever it (they) appear(s).
-----

Hence, I respectfully suggest that something like the following
code is non-portable and/or contrary to pANS:%%

    struct str { struct str *next; char string[0]; };

    char msg[] = "Toys r Us";
    struct str *ptr;

    ptr = (struct str *) malloc( sizeof(struct ptr) + strlen(msg) + 1 );
    strcpy( ptr->string , msg );
    ptr->string[5] = 'R';  /* Hmm, 5 is considerably past 0, yes?? */

In fact, one could argue that the strcpy is also illegal, since in the
course of copying the string, it would make an assignment to members
of the array too far past its end (i.e., subscripts of 1 and above).

Note: Obviously, if string[5] is illegal, you can't `make it legal' by
      writing it as *(string + 5).  Just to prevent questions of this sort...

------
%% Ignoring the presence of [0]; we all know that's non-pANS...
------

The question, as I see it, comes down to this:  Is it legal, on a purely
SEMANTIC basis, to exceed the _declared_ length of an _array_ , even
if we know that the actual memory is available and free?  
This as opposed to a DYNAMIC array, which is _not_ declared; e.g.

    type stat_array[ _size_ ];
    type *dyn_array;

That is, we all would agree that a construction such as
    dyn_array[ num ]
is perfectly legal in all contexts regardless of the magnitude of `num'
(provided dyn_array has been properly allocated),
but does pANS specifically FORBID or ENDORSE a construction such as
    stat_array[ num ]
where num >= _size_ + 1 ??
[This is EXPLICITLY forbidden for arrays that are NOT part of
dynamically-allocated structures (such as global array variables), isn't it?
The issue is whether it is legal for arrays that ARE part of dynamically-
allocated structures.]
I have an inkling that such a construction is forbidden, but I would
appreciate someone checking this out.  When I say `forbidden,' I mean
forbidden in all contexts -- regardless of whether or not stat_array[ num ]
refers to a properly allocated, reserved space.
If it is forbidden, then (unfortunately) it is impossible to simulate
a dynamic array by declaring a static array that is part of a dynamic
structure, which is essentially what everyone referring to the `need to
declare zero-length arrays as the last member of a structure' is trying
to do.  If it is not forbidden (and please cite chapter and verse), then
everything would be great and the restriction that zero-length arrays
cannot be DECLARED is definitely a hindrance to doing this sort of thing.

>As I recall, zero was invented by Arabic mathematicians
>thousands of years ago.  It's a pity it still frightens
>or confuses people.

I have no problem with zero, or zero-sized objects.  I do have problems
USING them as such, however.  Remember, you're trying to get away with
_changing the size_ of a DECLARED zero-sized object by arranging to
allocate (non-zero-sized) space for it.  The issue is whether the standard
permits this or not.  Heck, the issue is whether you can change the size
of a DECLARED array of ANY size by allocating space for it, zero-sized or
not.

> What fathomable purpose could a programmer possibly want by
> coding a loop that gets executed zero times?  To do nothing?

Now we see why this retort is not the same as the issue I raised.  Loops are
dynamic objects.  In general, we don't know how many times they execute
until run time.##  However, I am suggesting that declaring a zero-sized
array ( <type> array_name[0]; ) is in fact declaring a static object,
one whose length is known at compile-time, and whose length remains fixed --
just like _all_ arrays are in pANS C.  (Unless you can cite me chapter and
verse as above; then we have to change the word _all_ to `not-a-member of a
dynamically-allocated structure (sic)'.)  I think.

-----
## Yeah, yeah.  Sometimes we do.
-----

Okay....Comment, y'all !!  (Flames, as usual, go to Mssgrs. Bakker and Quayle.)

     __                        | Adam S. Denton - AT&T Bell Laboratories
   /   )       /               | 200 Laurel Avenue, Middletown, N.J. 07748
 /    /   __ /   ___   __ ___  | (201) 957-3499  Standard disclaimers apply.
(___/(__/(__(__/(__(__/  /  (_ | ...!att!mtqua!asd -or- asd@mtqua.ATT.COM

As a rule, avoid any animal that weighs over 300 pounds and has sharp teeth.
  -- rlp

P. S.  Anybody know how I can change the name postnews/rn uses?
I'd like to be known as `Adam S. Denton', not `adam.denton,mt,' !!