[net.lang.c] setjmp and typedef'd arrays; thoughts on &array

kendall@wjh12.UUCP (Sam Kendall) (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.
> -- 
> 			    Morris M. Keesan

   (I think you mean "jmp_buf foo, *tmp;".) The manual page implies that
jmp_buf is typedef'd to an array type, since the calls wouldn't work if
it weren't--you'd have to say "setjmp(&foo)" instead of "setjmp(foo)".
Sure enough, all UNIX implementations make jmp_buf an array type.  Now,
the type of "tmp", pointer to array, is fine, but the expression "&foo"
in "tmp = &foo" is not, because it is not legal to take the address of
an array with the address-of operator (somewhere in the Ref Man it says
an array is never an lvalue).  "&array" works on Ritchie cc's anyway,
as you note; but, quite properly, it won't work on others --in most
PCC's, the "&" is ignored.  "tmp = (jmp_buf *) foo" will work.

   Someone suggested that ATT allows assignment of jmp_buf's, etc.; this
is totally wrong (unless he is using a bizarre internal dialect).

> From: nazgul@apollo.uucp (Kee Hinckley)
> The whole point of a typedef (in my mind at least) is to create a
> level of abstraction that alleviates the need to learn what the machine/
> compiler architecture actually looks like.  To a certain degree typedef
> seems to succeed at this, but then it all falls apart.  Any thoughts?

   I agree, although the point is also to abstract away from what the
typedef'd type actually is, not just from the machine; the problem here
is that arrays behave differently from other types in C, and you can get
bitten with typedef'd arrays such as jmp_buf.  I feel strongly that one
should be able to take the address of an array with the address-of
operator, for reasons of orthogonality--in other words, so that the bite
would be a little less harsh.  The issue came before the ANSI C
committee this last meeting, and was voted down, so "&array" still
doesn't work.  The members seemed to feel that it was an extension,
rather than the removal of an anomalous restriction.  I have a pretty
good justification for feeling otherwise, which I'll post at some
point.

	Sam Kendall	  {allegra,ihnp4,ima,amd}!wjh12!kendall
	Delft Consulting Corp.	    decvax!genrad!wjh12!kendall

sdyer@bbncca.ARPA (Steve Dyer) (10/06/84)

When I first cut my teeth on C, in both the V6 and V7 Ritchie PDP-11 C
compilers, &array was accepted as a valid construct, and one which had
quite different semantics under pointer arithmetic from merely the array
name alone:

if we have

char x[10];

x + 1  points to the second char in the array, equivalent to &x[1].
&x + 1 points to the memory address FOLLOWING the entire array,
equivalent to &x[10].

That is, the size of the object pointed to is equal to the size of
the entire array.  Checking our present compiler, which is derived from
the Ritchie PDP-11 V7 compiler, it behaves in this manner.
-- 
/Steve Dyer
{decvax,linus,ima,ihnp4}!bbncca!sdyer
sdyer@bbncca.ARPA

bsa@ncoast.UUCP (Brandon Allbery) (10/07/84)

I think I have to clarify what I said in my last posting on this -- I
didn't explain why the &array was a no-no.  Forgive me if this is common
knowledge.

C purportedly handles arrays as if they were blocks of data and pointers.
However, it doesn't, quite.  The declaration

	char **foo, bar[10];

should allow me to say

	foo = &bar;

later on.h, since bar should be a pointer to char.  Unfortunately, bar
is what I call a VIRTUAL pointer -- it assembles as a literal (look at
your compiler's output).  To work correctly, it would have to assemble
to a constant pointer which always points to a particular block of memory,
in which case the above would work.  (Notice that the above is essentially
the jmp_buf, expanded.)  Instead, there is no such thing as &bar because
bar is not a variable, it is a literal.

One solution to this is to implement arrays as I showed above (in fact,
I considered writing a C-like language which used something like

	char ch*5; /* a (char *) whose value is the address of a block
		      of 5 characters */

but I don't think I can resolve possible conflicting uses of *); another
is to treat the jmp_buf typedef as having an implicit struct definition,
in which case the syntax

	jmp_buf *foo, bar;
	bar = &foo;

would expand to

	struct __jmp_buf {char jmp_buf[10];} *foo, bar;
	bar = &foo;

and since &struct is legal, it would work.  I think typedef should do
something like this, with `invisible' structs.  Anyone see problems with
it? (Probably; I've only been at this for a year. :-)

--bsa

mann@CSL-Vax.ARPA (Tim Mann) (10/13/84)

> C purportedly handles arrays as if they were blocks of data and pointers.
> However, it doesn't, quite.  The declaration
> 
> 	char **foo, bar[10];
> 
> should allow me to say
> 
> 	foo = &bar;
> 
> later on.h, since bar should be a pointer to char.  Unfortunately, bar
> is what I call a VIRTUAL pointer -- it assembles as a literal (look at
> your compiler's output).  To work correctly, it would have to assemble
> to a constant pointer which always points to a particular block of memory,
> in which case the above would work.  (Notice that the above is essentially
> the jmp_buf, expanded.)  Instead, there is no such thing as &bar because
> bar is not a variable, it is a literal.

This is not an anomaly, and there is no reason to invent the term "virtual
pointer".  In your example, "bar" is a constant of type pointer-to-char.  As
a constant, it does not have an address.  It is no more legitimate to write
&bar and expect to get the address of a cell containing bar's value, than it
would be to write &1 and expect to get the address of a cell with the value
1 in it.

I'm not going to try to respond to the other points in your message or the
other discussion that's been going on in this area just now.

	--Tim

stew@harvard.ARPA (Stew Rubenstein) (10/21/84)

> > C purportedly handles arrays as if they were blocks of data and pointers.
> > However, it doesn't, quite.  The declaration
> > 
> > 	char **foo, bar[10];
> > 
> > should allow me to say
> > 
> > 	foo = &bar;
> > 
> > later on.h, since bar should be a pointer to char.  Unfortunately, bar
> > is what I call a VIRTUAL pointer -- it assembles as a literal (look at
> > your compiler's output).  To work correctly, it would have to assemble
> > to a constant pointer which always points to a particular block of memory,
> > in which case the above would work.  (Notice that the above is essentially
> > the jmp_buf, expanded.)  Instead, there is no such thing as &bar because
> > bar is not a variable, it is a literal.
> 
> This is not an anomaly, and there is no reason to invent the term "virtual
> pointer".  In your example, "bar" is a constant of type pointer-to-char.  As
> a constant, it does not have an address.  It is no more legitimate to write
> &bar and expect to get the address of a cell containing bar's value, than it
> would be to write &1 and expect to get the address of a cell with the value
> 1 in it.
> 
> I'm not going to try to respond to the other points in your message or the
> other discussion that's been going on in this area just now.
> 
> 	--Tim

Ah, but Vax/VMS VAX-11 C *does* allow &1, meaning the address of a cell with
a 1 in it.  However, only for the special case of function call argument lists
so that you can pass a constant by reference to languages that don't have
call-by-value.
-- 
-----------------------
Stew Rubenstein     UUCP: ihnp4!harvard!stew
Harvard Chemistry   ARPA: stew@harvard