[net.lang.c] empty array declarations

judah@whuxcc.UUCP (Judah Greenblatt) (10/11/86)

Can anyone tell me why the following program is NOT in error?
Can anyone tell me what it MEANS?

	main()
	{
		int a[];

		a[0] = 5;
	}

Lint only complains about the random return value from main.
Most c compilers I tried (3B20, CCI 6/32, Pyramid 98x) accepted and executed
this program with no complaints.  The Sequent compiler accepted the
declaration and then gave a 'compiler error' message for the assignment.

In K&R [1], section 8.4, it states:
"..... the constant expressions which specify the bounds of the arrays may
be missing ....  This elision is useful when the array is external and the
actual definition, which allocates storage, is given elsewhere.  The first
constant-expression may also be omitted when the declarator is followed by
initialization."

This wording seems to allow the array size to be omitted anyplace,
but only assigns a meaning to the result for 'extern' arrays and where
there is an initializer.

I was recently bitten by code like this, and was wondering why it isn't
illegal to do such things.

----------
[1] Kernighan, Brian W. and Dennis M. Ritchie, "The C Programming Language",
    Prentice-Hall, Inc., 1978

-- 
Judah Greenblatt		"Backward into the Future!"
Bell Communications Research	uucp: {bellcore,infopro,ihnp4}!whuxcc!judah
Morristown, New Jersey, USA	arpa: whuxcc!judah@mouton.bellcore.com

rbutterworth@watmath.UUCP (Ray Butterworth) (10/14/86)

> Can anyone tell me why the following program is NOT in error?
> Can anyone tell me what it MEANS?
>     main()
>     {
>         int a[];
>         a[0] = 5;
>     }
> I was recently bitten by code like this, and was wondering why it isn't
> illegal to do such things.

It should be illegal.
Here's a change to the 4.2 source for /usr/src/lib/mip/pftn.c:

>  fixtype( p, class ) register NODE *p; {
>  ...
>      if( class==SNULL && blevel==1 && !(instruct&(INSTRUCT|INUNION)) )
>          class = PARAM;
>  #ifdef LINT    /* actually it should be a compiler error */
>      if (ISARY(type)){
>          if (dimtab[p->fn.cdim]==0){
>              if ((class==AUTO)
>               || (class==REGISTER))
>                  uerror("illegal null dimension array");
>          }
>      }
>  #endif /*LINT*/
>      if( class == PARAM || ( class==REGISTER && blevel==1 ) ){
>          if( type == FLOAT ) type = DOUBLE;
>          else if( ISARY(type) ){
>  #ifdef LINT
>              if (dimtab[p->fn.cdim]!=0)
>                  werror("array[%d] type changed to pointer",
>                      dimtab[p->fn.cdim]);
>  #endif /*LINT*/
>              ++p->fn.cdim;
>              type += (PTR-ARY);
>          }

The first change will complain about your example.
It probably should affect the compiler too
(i.e. get rid of the "#ifdef LINT").

The second change will warn about things like

>  func(a)
>      char a[17];
>  {
>      char b[17];
>  
>      if (sizeof(a)==sizeof(b))
>          printf("this machine has weird pointers\n");
>  }

If you really want to be daring, get rid of the "if (dimtab...!=0)"
in the second change.  Then it will complain about things like
   func(a)
       char a[];
   {
which really should be "char *a".

csanders@amdcad.UUCP (Craig S. Anderson) (10/16/86)

In article <1370@watmath.UUCP> rbutterworth@watmath.UUCP (Ray Butterworth) writes:
>
>If you really want to be daring, get rid of the "if (dimtab...!=0)"
>in the second change.  Then it will complain about things like
>   func(a)
>       char a[];
>   {
>which really should be "char *a".

That is only your opinion.  K&R states on page 95 that:
    "As formal parameters in a function definition,
	  char s[];
    and
	  char *s;
are exactly eqivalent; which one should be written is determined largely
how expressions will be written in the function..."



-- 
 Craig Anderson
 Advanced Micro Devices, Inc.
 (408) 749-3007
 UUCP: {ucbvax,decwrl,ihnp4,allegra,intelca}!amdcad!csanders
 #include <disclaimer.h>

throopw@dg_rtp.UUCP@ndmce.uucp (Wayne Throop) (10/17/86)

> judah@whuxcc.UUCP (Judah Greenblatt)

> Can anyone tell me why the following program is NOT in error?
No, because it IS in error.

> Can anyone tell me what it MEANS?
No, because it is meaningless.

(Please take both of the above answers to be flip or humorous.)

More seriously, declaring an automatic array with the number of elements
missing isn't stated explicitly to be an error in K&R, but we can infer
that it is meaningless, since there is no way to deduce the array size
by rules that *are* in K&R in such a case.  And both H&S and the draft
ANSI C standard explicitly make it illegal.

SysV.2 lint and many pcc compilers fail to note this error, and seem to
treat it as an array with no elements at all (and allocate no storage
for it, only an address... any subscription of the array at all is
out-of-bounds... not too useful).  Some compilers that label a
definition of an array with explicitly zero elements (as in "int a[0];")
as an error nevertheless treat "int a[];" as an array with implicitly
zero elements.  "Hard to believe!"

The DG C compiler says:

        int a[];
            ^
    You did not specify the array bounds for "a",
    either directly or implicity within an initialization.  You can omit
    only the first bound of an extern declaration or the first bound after
    a pointer.  The compiler used a bound of 1.

which is a tad friendlier than what pcc compilers do with it, which is
usually cause your program to blow up mysteriously later.

--
There are two ways to write error-free programs; only the third one works.
    --- Alan J. Perlis
-- 
Wayne Throop      <the-known-world>!mcnc!rti-sel!dg_rtp!throopw