A zero sized array declaration was a constraint violation (this requiring a diagnostic) in ISO C 90 in all contexts: even as a function parameter, where the identifier being declared is actually a pointer and not an array at all!<p>C99 added the &quot;flexible array member&quot; feature: the last element of a struct can be an array of size zero: &quot;As a special case, the last element of a structure with more than one named member may
have an incomplete array type; this is called a <i>flexible array member</i>.&quot; [C99, 6.7.2.1 ¶16]<p>In C90 code, the &quot;struct hack&quot; is implemented using an array of size [1] at the end of a struct. Some compilers allowed zero (like GNU C, I think) before C99.<p>In any case, supporting a [0]-sized array member which is not the last member of a struct, without issuing a diagnostic, is non-conforming.  The example given in the article with consecutive [0] arrays requires a diagnostic.<p>By the way, the (apparently only?) advantage of the flexible array member is that we can use sizeof (type) to obtain the size of the structure just excluding the first element of the array. Whereas with the C90 style struct hack, we must use offsetof(type, last_member) so that we exclude [1] from the calculation:<p><pre><code>  struct foo {
    &#x2F;* ... *&#x2F;
    int array[ZERO_OR_ONE];
  };

  &#x2F;* Correct in C99, if ZERO_OR_ONE is 0
     Incorrect in C90, (ZERO_OR_ONE can&#x27;t be zero).  *&#x2F;
  size_t foo_plus_3_elems = sizeof (struct foo) + 3 * sizeof(int);

  &#x2F;* Correct in C99 whether or not ZERO_OR_ONE is 0 or 1.
     Correct in C90 with ZERO_OR_ONE being 1. *&#x2F;
  size_t foo_plus_3_elems = offsetof (struct foo, array) + 3 * sizeof(int);
</code></pre>
Here, &quot;incorrect&quot; means we calculate slightly more storage than needed, usually without any downside.<p>&quot;Correct in C90&quot; means <i>de facto</i> correct, not that it was well-defined behavior. &quot;Everyone&quot; was doing it.