throopw@dg_rtp.UUCP (Wayne Throop) (08/04/86)
> whp@cbnap.UUCP (W. H. Pollock x4575 3S235) >> jcz@sas.UUCP (Carl Zeigler) >>Scan again, Andrew, the (void) values are being thrown away. > > The void values are not thrown away! Remember that (A?B:C) is an > expression *returning a value*. Uh, well, no actually. I'll join in this tis-so/tis-not debate using the radical approach of seeing what fairly-well-respected references have to say on the subject. First, note that K&R don't say anything about it, since they didn't have (void) back then. Second, Harbison and Steele say that ?: expressions come in four flavors. One flavor is interesting here (from page 183): 3. They [the second and third subexpressions] may have identical types (structure, union, enumeration, or void). The result is of this same type. Third, the ANSI C draft standard, C.3.15. The first operand shall have scalar type. Both the second and third operands shall have arithmetic type, or shall have the same structure, union, or pointer type, or shall be void expressions. In addition, one may be an object pointer and the other a pointer to void, or one may be a pointer and the other a null pointer constant. ... If both the operands are void expressions, the result is a void expression. All fairly clear and straightforward. It is legal. So, the objection: > C is giving the error because it can't > determine the type of the return value. is incorrect. The "type" returned from a ?: expression with void trailing operands is void. -- Any clod can have facts, but having opinions is an art. --- Charles McCabe, San Francisco Chronicle -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
franka@mmintl.UUCP (08/07/86)
[Not food] It seems clear that according to the ANSI draft, e1?e2:e3 is legal when e2 and e3 are both void. The next question is, should it be? It seems to me that there are two different paradigms for how to interpret the ?: operator here. One is as an ordinary operator, which returns one of the values of e2 or e3, depending on the value of e1. Under this interpretation, it does not seem to me appropriate to permit e2 and e3 void, since in that case they have no values. The other paradigm is that e1?e2:e3 is precisely one of e2 or e3, depending on the value of e1. This is a very reasonable interpretation; but if it were correct, there would be one other important consequence which is not in fact legal. This is that when e2 and e3 are lvalues, the compound expression should also be an lvalue. In particular, one could write e1?e2:e3 = e4; which would mean the same thing as if (e1) then e2 = e4; else e3 = e4; (This would be permitted only if e2 and e3 had exactly the same type, of course; one could not do this if e2 was a short and e3 a long.) This seems to me like a reasonable extension to the language. But I believe it should be one or the other -- the draft falls uncomfortably in the middle. Frank Adams ihnp4!philabs!pwa-b!mmintl!franka Multimate International 52 Oakland Ave North E. Hartford, CT 06108
jsdy@hadron.UUCP (Joseph S. D. Yao) (08/10/86)
In article <499@dg_rtp.UUCP> throopw@dg_rtp.UUCP (Wayne Throop) writes: >Any clod can have facts, but having opinions is an art. >> whp@cbnap.UUCP (W. H. Pollock x4575 3S235) >>> jcz@sas.UUCP (Carl Zeigler) >>>Scan again, Andrew, the (void) values are being thrown away. >> The void values are not thrown away! Remember that (A?B:C) is an >> expression *returning a value*. [paraphrase -j-] >K&R don't say anything, since no (void) back then. >Harbison and Steele say: > 3. They [the second and third subexpressions] may have identical > types (structure, union, enumeration, or void). The result is of > this same type. >ANSI C draft standard, C.3.15. > The first operand shall have scalar type. Both the second and third > operands shall have arithmetic type, or shall have the same > structure, union, or pointer type, or shall be void expressions. In > addition, one may be an object pointer and the other a pointer to > void, or one may be a pointer and the other a null pointer constant. > ... > If both the operands are void expressions, the result is a void > expression. >All fairly clear and straightforward. It is legal. *sigh* OK, let's get this straight. PROPOSED ANSI standard X3J11 describes a language (set of languages, over the past few years) that has (and have) not yet been implemented any- where by anyone (or if they have, word hasn't gotten to this corner yet). H&S, while a very good book, does take some liberties at interpretation. They are on the ANSI X3J11 committee, and could have been influenced in their interpre- tations by the committees deliberations. Most compilers today follow K&R, which by declaring that the conditional expression has (1) a result (2) with a data type predicated on the types of the operands, seems to be prohibiting use of void-type objects. Until recently, Proposed X3J11 concurred with this, specifically allowing only arith types, structures, unions, and pointers of the same type (remembering that "0" can be construed as a pointer of any type). Bottom line: it's a mite early to be pointing to Proposed X3J11 and saying something is "right" or "not right" based on that. Agreed, we should all follow and be aware (as I was not, of this) of things affecting our good programming practice. As of now, the standards are K&R with s3 and s5 enhancements. Anything that is not explicitly defined in one of these is subject to interpretation. As H&S points out, the C language is what the C compiler accepts. -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP} jsdy@hadron.COM (not yet domainised)
throopw@dg_rtp.UUCP (Wayne Throop) (08/11/86)
> franka@mmintl.UUCP (Frank Adams) > It seems clear that according to the ANSI draft, e1?e2:e3 is legal when e2 > and e3 are both void. The next question is, should it be? > It seems to me that there are two different paradigms for how to interpret > the ?: operator here. One is as an ordinary operator, which returns one of > the values of e2 or e3, depending on the value of e1. Under this > interpretation, it does not seem to me appropriate to permit e2 and e3 void, > since in that case they have no values. Well, not quite. The standard takes the position that, while a void expression has no value, it has something that is close enough for government work. A way to think of is that a void expression indicates a "value" which requires no storage and has no legal operations (other than selection operations). Then specifically, the ?: operation chooses which of these odd non-value values to "evaluate". > The other paradigm is that e1?e2:e3 is precisely one of e2 or e3, depending > on the value of e1. Yes. The standard doesn't go this way. But I think it is reasonable for the standard to go the way it does, making void expressions legal wherever any other expressions are, except that their result is illegal as input for any but selection operations, such as (?:) and (,). Any other operation implies an interpretation and transformation of a value, and (void) cannot be interpreted or transformed, but these operations only imply evaluation and selection. So I agree that there are two reasonable interpretations of (?:), and the standard has chosen the first. But it has also chosen an interpretation of "what it means to be (void)" which makes void expressions to the right of a "?" reasonable. -- If a listener nods his head when you're explaining your program, wake him up. --- Alan J. Perlis -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
geoff@desint.UUCP (Geoff Kuenning) (08/12/86)
While all of this discussion is very interesting and is important to achieving a precise language definition, let us not forget that there is *no* reason to ever write this particular expression. Anywhere it's useful, you can just write if (e1) void_e2; else void_e3; This is better style anyway; it makes use of a construct that people are much more used to, and it makes it clearer that what you are doing is picking one subroutine call over another, rather than something more subtle. If you really care about using precious lines, you can even put it on one line. -- Geoff Kuenning {hplabs,ihnp4}!trwrb!desint!geoff
bright@dataio.UUCP (Walter Bright) (08/13/86)
In article <243@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes: >While all of this discussion is very interesting and is important to >achieving a precise language definition, let us not forget that there >is *no* reason to ever write this particular expression. Anywhere it's >useful, you can just write > > if (e1) > void_e2; > else > void_e3; Not quite. This type of expression is very useful for macros which must in themselves be expressions (to avoid peculiar {} and ; problems). Such as: #define biff(pow) ((pow) ? kayo() : oof()) Defining the macro as: #define biff(pow) if (pow) kayo(); else oof(); causes difficulties with constructs like: if (socko) biff(flez); else bang(glurp); Similar problems exist for the other permutations of defining biff(). Now for the RIGHT (!) definition of when a void expressions is valid: A void expression is valid only under circumstances where the value of an expression is not used. This means that: (a ? voidexp : voidexp),(a=b) is valid. But a=a?voidexp:voidexp isn't valid, as the value is used. Apply the rule above to all the cases and you have the RIGHT (!) answer. Note that by implication, if the value of the ?: expression is not used, the operands of the : need not be of compatible types, and need not be brought to a common type. I would like to see the ANSI C spec clarified on this point.
brett@wjvax.UUCP (Brett Galloway) (08/14/86)
In article <243@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes: >While all of this discussion is very interesting and is important to >achieving a precise language definition, let us not forget that there >is *no* reason to ever write this particular expression. Anywhere it's >useful, you can just write > > if (e1) > void_e2; > else > void_e3; > You are correct, but this is true of ALL uses of '?:`. In fact, '?:` is VERY useful, especially when you want to embed conditionals in a macro. Using the if() {} else {} form restricts the contexts in which the macro may appear. -- ------------- Brett Galloway {pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett
davidsen@steinmetz.UUCP (Davidsen) (08/15/86)
In article <1701@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes: >The other paradigm is that e1?e2:e3 is precisely one of e2 or e3, depending >on the value of e1. This is a very reasonable interpretation; but if it >were correct, there would be one other important consequence which is not in >fact legal. This is that when e2 and e3 are lvalues, the compound >expression should also be an lvalue. In particular, one could write > >e1?e2:e3 = e4; > >which would mean the same thing as > >if (e1) then e2 = e4; else e3 = e4; > This kicked off an interesting thought: *(e1 ? <ptr expr> : <ptr expr>) = expr; Lo and behold it does what the quoted expression indicates. In an actual example: *(a < b : &b : &a) = 70; I'm not sure it *good* for anything, but if I do it with macros using cute names, I can enter it in the obfuscated C contest... -- -bill davidsen ihnp4!seismo!rochester!steinmetz!--\ \ unirot ------------->---> crdos1!davidsen chinet ------/ sixhub ---------------------/ (davidsen@ge-crd.ARPA) "Stupidity, like virtue, is its own reward"
levy@ttrdc.UUCP (Daniel R. Levy) (08/16/86)
In article <1061@dataio.UUCP>, bright@dataio.UUCP (Walter Bright) writes: >#define biff(pow) ((pow) ? kayo() : oof()) > >Defining the macro as: > >#define biff(pow) if (pow) kayo(); else oof(); > >causes difficulties with constructs like: > > if (socko) > biff(flez); > else > bang(glurp); > >Similar problems exist for the other permutations of defining biff(). Presuming that void kayo(), oof(); is intended, whatsa matter with #define biff(pow) { if (pow) kayo(); else oof(); } This combines the if-else into one single statement. There is a slight handicap that this doesn't work too well as the first operand of the comma operator ("syntax error") but at least some common modern C compilers (as on the SV 3B20) don't like Bright's macro either in this context or for that matter in any other context ("operands of : have incompatible types"). O.K., Bright (and others) have been saying "change the definition of C to allow this." Well I say the same thing about my suggestion, so THERE! :-) -- ------------------------------- Disclaimer: The views contained herein are | dan levy | yvel nad | my own and are not at all those of my em- | an engihacker @ | ployer or the administrator of any computer | at&t computer systems division | upon which I may hack. | skokie, illinois | -------------------------------- Path: ..!{akgua,homxb,ihnp4,ltuxa,mvuxa, go for it! allegra,ulysses,vax135}!ttrdc!levy
geoff@desint.UUCP (Geoff Kuenning) (08/16/86)
In article <745@wjvax.wjvax.UUCP> brett@wjvax.UUCP (Brett Galloway) writes: > In article <243@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes: >>let us not forget that there >>is *no* reason to ever write this particular expression. > You are correct, but this is true of ALL uses of '?:`. In fact, '?:` is > VERY useful, especially when you want to embed conditionals in a macro. > Using the if() {} else {} form restricts the contexts in which the macro > may appear. Unfortunately, Brett is incorrect here. You can't use if/then/else to write: for (i = up ? 0 : 99; up ? (i < 100) : (i >= 0); up ? i++ : i--) { /* complex loop body */ } without duplicating code. On the other hand, anywhere you want do if/then/else (or any other complex statement, such as loops and switches) inside a macro without restricting where the code can be used, you can just write: #define abc(x) do { \ /* anything you want goes here, even declarations */ \ } while (0) and almost all compilers will optimize the loop out completely (something that very few optimizers could do with the "complex loop body" above, especially because it trades time off for space and few compiler writers are willing to make that decision). I learned this method from in net.lang.c. -- Geoff Kuenning {hplabs,ihnp4}!trwrb!desint!geoff
brett@wjvax.UUCP (Brett Galloway) (08/19/86)
In article <248@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes: >In article <745@wjvax.wjvax.UUCP> brett@wjvax.UUCP (Brett Galloway) writes: > >> You are correct, but this is true of ALL uses of '?:`. In fact, '?:` is >> VERY useful, especially when you want to embed conditionals in a macro. >> Using the if() {} else {} form restricts the contexts in which the macro >> may appear. > >Unfortunately, Brett is incorrect here. You can't use if/then/else to write: > > for (i = up ? 0 : 99; up ? (i < 100) : (i >= 0); up ? i++ : i--) > { > /* complex loop body */ > } > I thought I said the same thing -- '?:` is useful in some cases where if/then/else isn't. >without duplicating code. On the other hand, anywhere you want do >if/then/else (or any other complex statement, such as loops and switches) >inside a macro without restricting where the code can be used, you can >just write: > > #define abc(x) do { \ > /* anything you want goes here, even declarations */ \ > } while (0) I don't think this method is general. For example, your macro abc() cannot be used inside a for() construct. -- ------------- Brett Galloway {pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett
cary@methods.UUCP (Cary Timar ) (08/26/86)
In article <248@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes: > >Unfortunately, Brett is incorrect here. You can't use if/then/else to write: > > for (i = up ? 0 : 99; up ? (i < 100) : (i >= 0); up ? i++ : i--) > { > /* complex loop body */ > } > >without duplicating code. On the other hand, anywhere you want do What about: if (up) { i = 0; step = 1; } else { i = 99; step = -1; } for (; i < 100 && i >= 0; i += step) { /* complex loop body */ } ???? -- Cary Timar /* NOT REACHABLE */ < Generic Disclaimer >
brett@wjvax.UUCP (Brett Galloway) (09/02/86)
In article <114@methods.UUCP> cary@methods.UUCP (Cary Timar (U of W co-op)) writes: >In article <248@desint.UUCP> geoff@desint.UUCP (Geoff Kuenning) writes: >> >>Unfortunately, Brett is incorrect here. You can't use if/then/else to write: >> >> for (i = up ? 0 : 99; up ? (i < 100) : (i >= 0); up ? i++ : i--) >> { >> /* complex loop body */ >> } I don't know what I originally said. What I MEANT to say was that the '?:` operator is useful. There are cases (such as within macros) where if/then/else is not appropriate. That's all. -- ------------- Brett Galloway {pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett