[net.lang.c] typedef gripe

nazgul@apollo.uucp (Kee Hinckley) (10/04/84)

...let's hear it for cut and paste...

>     "setjmp foo, *tmp; tmp = &foo;" is accepted with no complaints by my C
> compiler (based on the Dennis Ritchie V7 PDP11 "cc"), as it should be, because
> "tmp" and "&foo" have exactly the same (defined) type.  Either your C compiler
> has a bug in this respect, or your <setjmp.h> is #defining jmp_buf, instead of
> typedefing it.  The thing to do is not gripe about the language, but gripe to
> whomever maintains your compiler, to get this bug fixed.
> -- 
> 			    Morris M. Keesan
> 			    {decvax,linus,ihnp4,wivax,wjh12,ima}!bbncca!keesan
> 			    keesan @ BBN-UNIX.ARPA

Consider the following:
    char    c[10], *cptr;

    cptr = c;

    Clearly "c", without any subscripts is equivlent to "*cptr", I've yet to
see a C compiler complain about THAT line.  This means that "c" is a "pointer
to character", NOT a pointer to an array of characters.  Therefore taking
its address is equivilent to "&cptr", or asking for the address of the actual
pointer.
    Conceptually, "typedef" ought (my definition of ought) make the type into
an abstract object, which no longer depends upon the fact that it used to be an
array.  In fact it does not, and thus:

    typedef char jmp_buf[10];
    jmp_buf c, *cptr;

    cptr = &c;

ends up being incorrect.

Now, just in case you think my compiler is strange (Apollo CC).  Here is
the Berkeley 4.2 example.

    %8% cat foo.c
    typedef char jmp_buf[10];
    main()
    {
            jmp_buf c, *cptr;
    
            cptr = c;
            cptr = &c;
            cptr = (jmp_buf *) &c;
            cptr = (jmp_buf *) c;
    }
    %9% cc foo.c
    "foo.c", line 6: warning: illegal pointer combination
    "foo.c", line 7: warning: & before array or function: ignored
    "foo.c", line 7: warning: illegal pointer combination
    "foo.c", line 8: warning: & before array or function: ignored
    %10% 
----------------------
Apollo CC
----------------------
-=> catf foo.c
    typedef char jmp_buf[10];
    main()
    {
            jmp_buf c, *cptr;
    
            cptr = c;
            cptr = &c;
            cptr = (jmp_buf *) &c;
            cptr = (jmp_buf *) c;
    }
-=> cc foo.c

 (0006)             cptr = c;
******** Line 6: Warning:  Illegal pointer combination: incompatible types.

 (0007)             cptr = &c;
******** Line 7: Warning:  Illegal pointer combination: incompatible types.
No errors, 2 warnings, C Compiler, Rev 2.40

--------------------------------------------------
Now I'm not saying that Berkeley has the right error messages either,
in particular the complaints about the '&'s are completely out of place
given that typedef is *supposed* to make things more data independant.
I might note however, that our version of PCC also complains about 
incompatable types (although not the '&').

What's the correct answer?  I don't know.  Probably the best thing to do
is avoid typedef'ing arrays completely.


                                            -kee
                                ...decvax!wivax!apollo!nazgul

martillo@mit-athena.ARPA (Joaquim Martillo) (10/05/84)

>>     "setjmp foo, *tmp; tmp = &foo;" is accepted with no complaints by my C
>> compiler (based on the Dennis Ritchie V7 PDP11 "cc"), as it should be, because
>> "tmp" and "&foo" have exactly the same (defined) type.  Either your C compiler
>> has a bug in this respect, or your <setjmp.h> is #defining jmp_buf, instead of
>> typedefing it.  The thing to do is not gripe about the language, but gripe to
>> whomever maintains your compiler, to get this bug fixed.
>> -- 
>> 			    Morris M. Keesan
>> 			    {decvax,linus,ihnp4,wivax,wjh12,ima}!bbncca!keesan
>> 			    keesan @ BBN-UNIX.ARPA
>
>Consider the following:
>    char    c[10], *cptr;
>
>    cptr = c;
>
>    Clearly "c", without any subscripts is equivlent to "*cptr", I've yet to
>see a C compiler complain about THAT line.  This means that "c" is a "pointer
>to character", NOT a pointer to an array of characters.  Therefore taking
>its address is equivilent to "&cptr", or asking for the address of the actual
>pointer.
>    Conceptually, "typedef" ought (my definition of ought) make the type into
>an abstract object, which no longer depends upon the fact that it used to be an
>array.  In fact it does not, and thus:
>
>    typedef char jmp_buf[10];
>    jmp_buf c, *cptr;
>
>    cptr = &c;
>
>ends up being incorrect.
>
>Now, just in case you think my compiler is strange (Apollo CC).  Here is
>the Berkeley 4.2 example.
>
>    %8% cat foo.c
>    typedef char jmp_buf[10];
>    main()
>    {
>            jmp_buf c, *cptr;
>    
>            cptr = c;
>            cptr = &c;
>            cptr = (jmp_buf *) &c;
>            cptr = (jmp_buf *) c;
>    }
>    %9% cc foo.c
>    "foo.c", line 6: warning: illegal pointer combination
>    "foo.c", line 7: warning: & before array or function: ignored
>    "foo.c", line 7: warning: illegal pointer combination
>    "foo.c", line 8: warning: & before array or function: ignored
>    %10% 
>----------------------
>Apollo CC
>----------------------
>-=> catf foo.c
>    typedef char jmp_buf[10];
>    main()
>    {
>            jmp_buf c, *cptr;
>    
>            cptr = c;
>            cptr = &c;
>            cptr = (jmp_buf *) &c;
>            cptr = (jmp_buf *) c;
>    }
>-=> cc foo.c
>
> (0006)             cptr = c;
>******** Line 6: Warning:  Illegal pointer combination: incompatible types.
>
> (0007)             cptr = &c;
>******** Line 7: Warning:  Illegal pointer combination: incompatible types.
>No errors, 2 warnings, C Compiler, Rev 2.40
>
>--------------------------------------------------
>Now I'm not saying that Berkeley has the right error messages either,
>in particular the complaints about the '&'s are completely out of place
>given that typedef is *supposed* to make things more data independant.
>I might note however, that our version of PCC also complains about 
>incompatable types (although not the '&').
>
>What's the correct answer?  I don't know.  Probably the best thing to do
>is avoid typedef'ing arrays completely.
>
>
>                                            -kee
>                                ...decvax!wivax!apollo!nazgul
>
>
>

Apollo is correct and Berkeley is wrong at least as I understand how C
compilers work at ATT.  A jmp_buf is not exactly an array.  It is a
fixed length, array, i. e. a block of memory of known size a.k.a
structure.  Thus at ATT if new_jmp_buf and old_jmp_buf are defined as
jmp_buf's 

		jmp_buf new_jmp_buf, old_jmp_buf;

		..........		/* Fill up old_jmp_buf */

		..........

		new_jmp_buf = old_jmp_buf;

works (or should work).

Therefore, just as

		struct tag node, *p = &node;

works so should

		jmp_buf save, *p = &save;

also work.

martillo@mit-athena.ARPA (Joaquim Martillo) (10/05/84)

Sorry, rereading the article, I realize both Berkeley and Apollo are
wrong and that ATT is correct.

chris@umcp-cs.UUCP (Chris Torek) (10/06/84)

One can always (sigh) cheat and write

	typedef struct {
		int a[10];
	} jmp_buf;

There is an obvious problem with changing the language such that

	typedef int foo[10];

makes ``foo'' a type which is considered a unit (like structs and
unions and basic types), and that is that it would probably break
quite a bit of existing code.
-- 
(This mind accidently left blank.)

In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

guy@rlgvax.UUCP (Guy Harris) (10/06/84)

>...> Discussion of "jmp_buf" typedefed as an array causing various
>...> compilation errors.
> 
> Apollo is correct and Berkeley is wrong at least as I understand how C
> compilers work at ATT.  A jmp_buf is not exactly an array.  It is a
> fixed length, array, i. e. a block of memory of known size a.k.a
> structure.

Not as of System V Release 2; it's still an array, not a structure, in the
include file "setjmp.h".  Thus, the example you give later of structure
copying between "jmp_buf"s won't work either.  Maybe some non-mainstream
versions of UNIX have defined it as a structure (it probably should be so
defined, 1) because it doesn't do any harm, 2) because structures, unlike
arrays, can be dealt with in a semi-abstract fashion and won't cause problems
when you stick an "&" in front of one's name, and 3) because that way you
can put mnemonic names on the elements of the jmp_buf, so you can figure out
"OK, it sticks the current frame pointer in the fifth word").

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

geoff@desint.UUCP (Geoff Kuenning) (10/06/84)

>What's the correct answer?  I don't know.  Probably the best thing to do
>is avoid typedef'ing arrays completely.
>				Kee Hinckley

Amen!  Note that if the guy who typedef'ed jmp_buf had made it a struct, not
only would it have been more flexible, but the construct under discussion
("jmp_buf c, *cp;  cp = &c;") would have been perfectly legal.  Now, of
course, there are thousands of people out there who have been forced to write
code that assumes jmp_buf is an array, so fixing the typedef to be a struct
like it should have in the first place will break all that code.  *SIGH*.

(I was never too happy with the idea of typedef'ing something as a fixed-size
array, anyway.  Doesn't sit well with my hick notions of what a typedef out to
be.)
-- 
	Geoff Kuenning
	First Systems Corporation
	...!ihnp4!trwrb!desint!geoff

warren@tikal.UUCP (warren) (10/10/84)

[There are no bugs]

	It seems to me that typedef'ing something to an array uncovers
	some ambiguity in the C language, in that array names are
	constants, not variables.  Typedef'ing to a constant is rather
	odd to begin with.  One feels it perhaps ought to be illegal.
	Or at least very rude.  For example, would you accept
	"typedef 7 foo;" ?

	Array names are "pointer constants" of the type of "pointer to
	the first element of the array".  Other languages and machines
	used to call this sort of thing an "address constant".

	Of course, there is an inconsistancy.  The "sizeof(arrayname)"
	expression is the number of bytes in all the elements of the
	array.  Furthermore, when an arrayname is passed as the actual
	argument to a function, the formal function argument (in the
	function) has some other size entirely.  On machines that
	do not address a byte directly, the number of bytes in array
	of pointers or of floating point constants does not even
	have to be an integer !  

					teltone!warren