[comp.lang.c] zero length array

Dizio@udel.edu (02/17/87)

Not to nit pick but is it always true that within the structure 

struct LINE {
        struct header_junk hj;
        char   text[32768];
         } ;

'text' falls immediately after 'hj'?  If not I would be wary
about mallocing sizeof(header_junk) + length.

II.
   Is the following a portable way of finding out where a field
within a structure is located?

    & (((struct any_struct_tag *) 0)->any_field)


Dave DiZio

msb@sq.UUCP (02/19/87)

Dizio@udel.edu writes:
> Not to nit pick but is it always true that within the structure 
> 
>    struct LINE { struct header_junk hj; char text[32768]; } ;
> 
> 'text' falls immediately after 'hj'?

It isn't guaranteed.  A compiler is allowed to leave space in there
according to the type of the following member, i.e., char[] here.
However, any extra space required for alignment of the inner struct
will be counted as part of that struct.

It seems most unlikely that "char[]" could have alignment requirements
more strict than a struct, but there is nothing forbidding it.

>    Is the following a portable way of finding out where a field
> within a structure is located?
>     & (((struct any_struct_tag *) 0)->any_field)

No.  When 0 is converted to pointer type (remember, a cast is a conversion),
all you know is that the resulting pointer doesn't point to a valid object.
In this case there are certainly machines where it's not a numeric 0.

You need an actual object of the struct type, say tmp; and then, of course,
you can say:

	(char *) &tmp.any_field - (char *) &tmp

In the current ANSI draft, there is a predefined macro "offsetof" which
does something like this for you without needing you to specify an object.

However, I've never met a case where this operation was really necessary.
Usually the job can be done more comprehensibly with unions.

Mark Brader, utzoo!sq!msb			C unions never strike!

john@viper.UUCP (02/21/87)

In article <1987Feb19.134433.737@sq.uucp> msb@sq.UUCP (Mark Brader) writes:
 >
 >You need an actual object of the struct type, say tmp; and then, of course,
 >you can say:
 >
 >	(char *) &tmp.any_field - (char *) &tmp
 >
 >In the current ANSI draft, there is a predefined macro "offsetof" which
 >does something like this for you without needing you to specify an object.
 >
 >However, I've never met a case where this operation was really necessary.
 >Usually the job can be done more comprehensibly with unions.
 >
 >Mark Brader, utzoo!sq!msb			C unions never strike!

  Mark,
I agree with you that the other construct is poor, that the one you gave
is considerably better, but I disagree with you on the subject of unions.
  I've had experience with many (far -too- many) compilers that have
multiple bugs in the handleing of unions.  For portability, it's best
to -not- use unions in general, and in this instance especialy.  (Unions
are in many cases totaly non-portable across systems with different byte
order rules.  And there is more than one compiler that fails to poperly
handle increment/decrement if you have a union consisting of several
pointer types...)
 
  The best solution I've come up with is as follows:
 
#define ANOFFSET (int)(((char*)&tmp.any_field) - ((char*)&tmp))
 
  The construct you created will be typed as an int on some systems and
as a long on others.  This means you can't portably use it in a
parameter list.  Adding the (int) (or (long)) cast at the beginning
solves this portability problem.

----
John Stanley (john@viper.UUCP) - DynaSoft Systems 

woods@gpu.utcs.toronto.edu (02/26/87)

In article <4498@brl-adm.ARPA> Dizio@udel.edu writes:
>   Is the following a portable way of finding out where a field
>within a structure is located?
>
>    & (((struct any_struct_tag *) 0)->any_field)

Not that I know of, though the expression without "&" is usefull in sizeof().

Some compilers will refuse to cast NULL, specifically Lattice C up to 2.15(?)
As far as I know all Unix compilers will cast NULL.

You might want to cast one(1) instead.  Lattice will accept this.

						Greg Woods.

jpn@teddy.UUCP (02/27/87)

>>   Is the following a portable way of finding out where a field
>>within a structure is located?
>>
>>    & (((struct any_struct_tag *) 0)->any_field)
>
>Some compilers will refuse to cast NULL, specifically Lattice C up to 2.15(?)
>As far as I know all Unix compilers will cast NULL.

If true, then Lattice is seriously broken.  Are you saying that I can't say
time ((long *) 0) in Lattice C?  Or execl(pgmname, arg0, arg1, (char *) 0)?
If it can't do these things, then it isn't a C compiler!!
.
.
. (I hate the 2.11 inews)
.
.

woods@gpu.utcs.toronto.edu (02/28/87)

I guess we are getting a little off topic here, but anyway...

I haven't used Lattice in a long time (and I'd rather not), but as far
as I can remember, the casting of zero (0) works, except when used to
reference a structure member, especially in a sizeof() expression:

	sizeof(((struct xyzzy *) 0)->member)

My original article may not have made this clear.

						Greg Woods.

meissner@dg_rtp.UUCP (Michael Meissner) (03/06/87)

In article <1987Feb25.201816.29714@gpu.utcs.toronto.edu> woods@gpu.utcs.UUCP (Greg Woods) writes:
> In article <4498@brl-adm.ARPA> Dizio@udel.edu writes:
> >   Is the following a portable way of finding out where a field
> >within a structure is located?
> >
> >    & (((struct any_struct_tag *) 0)->any_field)
> 
> Not that I know of, though the expression without "&" is usefull in sizeof().
> 
> Some compilers will refuse to cast NULL, specifically Lattice C up to 2.15(?)
> As far as I know all Unix compilers will cast NULL.
> 
> You might want to cast one(1) instead.  Lattice will accept this.
> 
> 						Greg Woods.

I believe the harris compiler also has problems with this.  Also any
implementation which does not produce all zero bits for integer 0 -> pointer
(or vica versa) would have problems with this.  That's why offsetof was
created in ANSI.
-- 
	Michael Meissner, Data General	Uucp: ...mcnc!rti-sel!dg_rtp!meissner

It is 11pm, do you know what your sendmail and uucico are doing?