evil@arcturus.UUCP (Wade Guthrie) (10/26/88)
Is the following code portable, strictly conforming, etc. a = function()->member; as in something like the following (really simplified) code: union yowza { int i; float f; char *c; }; union yowza *yikes() /* actually, I pass the type here */ { static union yowza fubar; fubar.i = 6; /* and I make the assignment based on the type */ return (&fubar); } main() { union yowza *yikes(); int j; . . . j = yikes()->i; } It works on (shudder) a VAX running VMS, and for this reason, I suspect it is not portable -- can anyone help? Wade Guthrie Rockwell International Anaheim, CA (Rockwell doesn't necessarily believe / stand by what I'm saying; how could they when *I* don't even know what I'm talking about???)
chris@mimsy.UUCP (Chris Torek) (10/27/88)
In article <2205@arcturus> evil@arcturus.UUCP (Wade Guthrie) writes: >Is the following code portable, strictly conforming, etc. > a = function()->member; >as in something like the following (really simplified) code: [deleted] It is conforming, etc., if function() returns a pointer to a structure or union and the `member' field corresponds to a member of that structure or union. Likewise, a = function().member; is conforming, etc., if function() returns a structure or union and the `member' field corresponds, etc., with one additional restriction: the member must not be an array. Nonetheless, the second form is another one of those things that compilers have got wrong in the past; you are better off with lump = function(); a = lump.member; -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
gwyn@smoke.BRL.MIL (Doug Gwyn ) (10/27/88)
In article <2205@arcturus> evil@arcturus.UUCP (Wade Guthrie) writes: >Is the following code portable, strictly conforming, etc. > a = function()->member; There are probably implementations that don't support this. However, in ANSI C functions can return (rvalue) structures. Since the function value is not an lvalue, neither will the result of the member-of operator be an lvalue. Thus, sfunc().member = a; is invalid. (There should be no such problem with structure pointers and ->.)
maart@cs.vu.nl (Maarten Litmaath) (10/28/88)
In article <14172@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
\ a = function().member;
\
\is conforming, etc., if function() returns a structure or union and the
\`member' field corresponds, etc., with one additional restriction:
\the member must not be an array.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why?
--
George Bush: |Maarten Litmaath @ VU Amsterdam:
Capt. Slip of the Tongue |maart@cs.vu.nl, mcvax!botter!maart
chris@mimsy.UUCP (Chris Torek) (10/28/88)
... and union func(): >In article <14172@mimsy.UUCP> I noted that >> a = function().member; >> >>is conforming, etc., if function() returns a structure or union and the >>`member' field corresponds, etc., with one additional restriction: >>the member must not be an array. In article <1585@solo8.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) asks why the restriction exists. `function().member' above is used in an rvalue context; as such, if the member is an array, this amounts to taking the address of part of a structure or union valued function. If, as is common in some compilers, the return value is in fact copied into local temporary storage, it may not have an address. In particular, consider the following: struct arr { int arr[10]; }; struct arr fn(); main() { int *p; p = &fn().arr[8]; printf("fn 3,4 = %d,%d; p = %p\n", p[0], p[1], (void *)p); } This might `want' to compile into something like this: main_: | { mov fp,-(sp) | make stack frame mov sp,fp | int *p; sub #2,sp | make stack space for local `p' | fn() sub #20,sp | make room lea (sp),r0 | address of return space call fn_ | fn() lea (sp),r0 | compute address of return value | & .arr[8] lea 16(r0),r0 | p = mov r0,-2(fp) | store in p | ; add #20,sp | done with return value | p mov -2(fp),r0 | noop, hope optimiser pulls it out mov r0,-(sp) | push p | p[1] mov -2(fp),r0 | noop, hope optimiser pulls it out mov 2(r0),-(sp) | push p[1] | p[0] mov (r0),-(sp) | push p[0] | "string" pea S1 | push address of string | printf(...) call printf_ | printf the various variables add #8,sp | fix stack | } mov fp,sp | undo frame mov (sp)+,fp ret There is a problem here: pushing p clobbered p[1]! Anyway, it is legislated out, as is such stuff as struct arr fn(); main() { fn().arr[2] = 3; } (At least, I *hope* stuff like the latter is illegal, given that the point of the original restriction above is to allow structure return values to be done using invisible temporaries....) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
guido@cwi.nl (Guido van Rossum) (10/28/88)
In article <14201@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >In article <1585@solo8.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) asks >why the restriction exists. Chris's original posting said that "v = func().a" is legal, unless a is an array. The reason was that C has no array assignment, not that there's anything special with array members of structs returned by functions. A less confusing way to state the ruls is that "func().a" is legal, but as an rvalue only. -- Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam guido@piring.cwi.nl or mcvax!piring!guido or guido%piring.cwi.nl@uunet.uu.net
lai@vedge.UUCP (David Lai) (10/29/88)
In article <2205@arcturus> evil@arcturus.UUCP (Wade Guthrie) writes: >Is the following code portable, strictly conforming, etc. > a = function()->member; >as in something like the following (really simplified) code: >(proceeds to describe the union pointer of the function return type...) >It works on (shudder) a VAX running VMS, and for this reason, I >suspect it is not portable -- can anyone help? It works on suns and hp-ux (sys V) machines also. However I read somewhere (Harbison & Steele): -> operator requires an object that is an lvalue a function call is NEVER an lvalue So there is some discrepency here. Anyone care to comment on what ANSI says? -- "What is a DJ if he can't scratch?" - Uncle Jamms Army The views expressed are those of the author, and not of Visual Edge, nor Usenet. David Lai (vedge!lai@larry.mcrcim.mcgill.edu || ...watmath!onfcanim!vedge!lai)
chris@mimsy.UUCP (Chris Torek) (10/30/88)
In article <1770@vedge.UUCP> lai@vedge.UUCP (David Lai) writes: >... I read somewhere (Harbison & Steele): > > -> operator requires an object that is an lvalue This is false. -> *produces* an lvalue (with the usual exceptions for arrays); it does not *require* one. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
guido@cwi.nl (Guido van Rossum) (10/31/88)
In article <7686@boring.cwi.nl> I wrote: >Chris's original posting said that "v = func().a" is legal, unless a is >an array. The reason was that C has no array assignment, not that >there's anything special with array members of structs returned by >functions. A less confusing way to state the rules is that "func().a" is >legal, but as an rvalue only. I received a mail message stating that in fact *any* use of func().a is illegal when a is an array member; the reason being that this use of an array name requires conversion to a pointer to its first element, and of course Chris has adequately explained why that should be illegal. I suppose that it is thus even illegal to write something like "v = func().a[0]", even though that would make perfect sense (all Chris's examples showed cases where a's address or the address of some element was actually saved). I suppose it would be possible to change various rules about pointers, arrays, rvalues and lvalues to fix this, but nobody cared. -- Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam guido@piring.cwi.nl or mcvax!piring!guido or guido%piring.cwi.nl@uunet.uu.net
norvell@csri.toronto.edu (Theodore Stevens Norvell) (11/04/88)
In article <7689@boring.cwi.nl> guido@cwi.nl (Guido van Rossum) writes: >In article <7686@boring.cwi.nl> I wrote: >>Chris's original posting said that "v = func().a" is legal, unless a is >>an array. > >I received a mail message stating that in fact *any* use of func().a is >illegal when a is an array member; the reason being that this use of an >array name requires conversion to a pointer to its first element, and of >course Chris has adequately explained why that should be illegal. > >I suppose that it is thus even illegal to write something like >"v = func().a[0]", even though that would make perfect sense (all >Chris's examples showed cases where a's address or the address of some >element was actually saved). I suppose it would be possible to change >various rules about pointers, arrays, rvalues and lvalues to fix this, >but nobody cared. [I presume you mean ``nobody cared to do so'', or, to put it more positively, that the commttee cared that the indexing rules were simple and uniform. :-)] Yes. func().a[0] is not legal. The problem with it is that the proposed standard defines array indexing in terms of addresses. The example is equivalent to *(func().a + 0) where func().a is the address of the first element of the array. But, as the array (being a member of an rvalue) does not have an address, it does not make sense (even though it is clear what is meant). It is still not clear to me that func().a itself is illegal, though it is clear that its use is limited. Perhaps someone who knows the proposed standard intimately would care to comment on whether, for example, sizeof( func().a ) is legal. Note that, contrary to the mail message Guido recieved, in ANSI C, arrays arguments to sizeof are not coerced to pointers. If func().a is not legal can someone explain exactly why. Theodore Norvell norvell@csri.utoronto utzoo!utcsri!norvell