burow@cernvax.cern.ch (burkhard burow) (02/14/91)
I'm wondering if anyone has any comments on using: *(a==b?&c:&d) = 1; instead of: if (a==b) c=1; else d=1; thanks, burkhard burow%13313.hepnet@csa3.lbl.gov
johnm@cory.Berkeley.EDU (John D. Mitchell) (02/14/91)
In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >I'm wondering if anyone has any comments on using: > *(a==b?&c:&d) = 1; >instead of: > if (a==b) c=1; > else d=1; 1) Readability, readability, READABILITY! 2) Why? It's not any faster. Ugh, John D. Mitchell johnm@cory.Berkeley.EDU P.S. No wonder people complain about the denseness of C code!
gwyn@smoke.brl.mil (Doug Gwyn) (02/14/91)
In article <11073@pasteur.Berkeley.EDU>, johnm@cory.Berkeley.EDU (John D. Mitchell) writes: - In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: - >I'm wondering if anyone has any comments on using: - > *(a==b?&c:&d) = 1; - >instead of: - > if (a==b) c=1; - > else d=1; My comment was going to be that it sucked bigtime. However, I'll buy "ugh" as a suitable comment too. - P.S. No wonder people complain about the denseness of C code! C code has nothing to do with it, more like the density of some coders.
paulb@ssd.csd.harris.com (Paul Beusterien) (02/14/91)
In article <11073@pasteur.Berkeley.EDU> johnm@cory.Berkeley.EDU (John D. Mitchell) writes: :In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: ::I'm wondering if anyone has any comments on using: :: *(a==b?&c:&d) = 1; ::instead of: :: if (a==b) c=1; :: else d=1; : :1) Readability, readability, READABILITY! : :2) Why? It's not any faster. Its probably slower, since it is a lot less likely the compiler will keep c and d in registers. -- Paul Beusterien paulb@ssd.csd.harris.com Harris Computer Systems {uunet,mit-eddie,novavax}!hcx1!paulb Ft. Lauderdale, FL voice: (305) 973 5270
kdq@demott.com (Kevin D. Quitt) (02/14/91)
In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >I'm wondering if anyone has any comments on using: > > *(a==b?&c:&d) = 1; > >instead of: > > if (a==b) c=1; > else d=1; It's cryptic and ugly, therefore harder to maintain. It also produces identical code (gcc, MSC 6.0). It *does* save several bytes of storage. -- _ Kevin D. Quitt demott!kdq kdq@demott.com DeMott Electronics Co. 14707 Keswick St. Van Nuys, CA 91405-1266 VOICE (818) 988-4975 FAX (818) 997-1190 MODEM (818) 997-4496 PEP last
ckp@grebyn.com (Checkpoint Technologies) (02/14/91)
In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >I'm wondering if anyone has any comments on using: > > *(a==b?&c:&d) = 1; > >instead of: > > if (a==b) c=1; > else d=1; Sure, I have a comment. My own opinion, of course, since both are valid C and should produce identical results. In nearly all cases I would use the second form. It's easier to read. In fact I had to go over the first one twice to assure myself that it does what the second clearly states, and clarity is a critical feature of any program. Note also that the first form won't necessarily work if either c or d are register variables. The only time I would use the first form is in a macro, in a situation where I really wanted an expression rather than a statement. But that's all. -- First comes the logo: C H E C K P O I N T T E C H N O L O G I E S / / \\ / / Then, the disclaimer: All expressed opinions are, indeed, opinions. \ / o Now for the witty part: I'm pink, therefore, I'm spam! \/
karl@ima.isc.com (Karl Heuer) (02/14/91)
In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: > *(a==b?&c:&d) = 1; What you really want is (a==b?c:d) = 1; which should (IMHO) be legal (i.e. the result of ?: is an lvalue if both subexpressions are lvalues), but this isn't the case in Standard C. (But GCC supports it as a non-standard extension.) So far everyone has complained about using ?: instead of the "clearer" method of putting the assignment inside the conditional. Nobody has mentioned yet that the above form does have one advantage, which becomes more obvious when the RHS is a complicated expression: you can write it just once without using a temporary. If the GCC extension were standard, I'd use it in such a case (just as I use x=(a==b?c:d) in real C when appropriate). But since it isn't, and making it legal by adding the extra *...&...& is a lose, I'd probably declare a temp variable and use (a==b?c=T:d=T) instead. (Or the equivalent if-else form, if it's in a statement context.) Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint
suhonen@kunto.jyu.fi (Timo Suhonen) (02/14/91)
burow@cernvax.cern.ch (burkhard burow) writes:
I'm wondering if anyone has any comments on using:
*(a==b?&c:&d) = 1;
instead of:
if (a==b) c=1;
else d=1;
OK. I have one: The if - else -statement is much more readable than the other
one. Have look with a compiler wich one if faster...
--
Timo Suhonen I am logged in, therefore I am suhonen@nic.funet.fi
suhonen@kunto.jyu.fi
Opinions(?) are mine (if not stolen), NOT those of Univ. of Jyvaskyla.
johnm@cory.Berkeley.EDU (John D. Mitchell) (02/14/91)
In article <15184@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >In article <11073@pasteur.Berkeley.EDU>, johnm@cory.Berkeley.EDU (John D. Mitchell) writes: [....] >My comment was going to be that it sucked bigtime. However, I'll >buy "ugh" as a suitable comment too. I decided that sucked s#!t was too harsh. :-) >- P.S. No wonder people complain about the denseness of C code! >C code has nothing to do with it, more like the density of some coders. Well, a lot of people (wrongly) criticize the *language* when it's really the (your flame here) coder that makes the source code atrocious. I mean, we're not talking about entries for the obfuscated C code contest! ---- John D. Mitchell johnm@cory.Berkeley.EDU
richard@aiai.ed.ac.uk (Richard Tobin) (02/14/91)
In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >I'm wondering if anyone has any comments on using: > > *(a==b?&c:&d) = 1; Yes, it's ugly and pointless, and furthermore prevents c and d from being in registers. By the way, gcc allows as an extension (a == b ? c : d) = 1; which is much more reasonable. -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
volpe@camelback.crd.ge.com (Christopher R Volpe) (02/14/91)
In article <15184@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes: |>In article <11073@pasteur.Berkeley.EDU>, johnm@cory.Berkeley.EDU (John D. Mitchell) writes: |>- In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: |>- >I'm wondering if anyone has any comments on using: |>- > *(a==b?&c:&d) = 1; |>- >instead of: |>- > if (a==b) c=1; |>- > else d=1; |> |>My comment was going to be that it sucked bigtime. However, I'll |>buy "ugh" as a suitable comment too. Yes, it's ugly, but it's conceivable that someone might have a good reason for defining a macro to do this, so that the macro may be used in an expression context. ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
johnm@cory.Berkeley.EDU (John D. Mitchell) (02/15/91)
In article <16754@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes: [....] >Yes, it's ugly, but it's conceivable that someone might have a good >reason for defining a macro to do this, so that the macro may be used >in an expression context. Aahhh! But context *is* everything. One reason to use macros is to hide this sort of cryptic code behind a nice facade. Oh well... if only C had... :-) ---- John D. Mitchell johnm@cory.Berkeley.EDU
scc@rlgvax.Reston.ICL.COM (Stephen Carlson) (02/15/91)
In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >I'm wondering if anyone has any comments on using: > > *(a==b?&c:&d) = 1; >instead of: > if (a==b) c=1; > else d=1; > The GNU C compiler as an extension to the C programming language allows the result of the ternary operator to be an lvalue: ((a == b) ? c : d) = 1; Normal C, however, requires that the result of the ternary operator be an rvalue, hence the subterfuge with the & and * operators (the result of a * operator is an lvalue). My only remark is that this may be preferable in the case where the right hand of side of the expression is some long expression, like: *(a==b?&c:&d) = some_long_and_hairy_expression; Since it written only once and not twice, there is less chance for errors due to inconsistencies, as in: if (a == b) c = some_long_and_hairy_expression; else d = some_lomg_and_hairy_expression; Here, those two long expressions are not the same and it is not clear to the maintainer whether they should be the same. To paraphrase Aristotle, same things should be the same; different things different. The same argument is the basis for the += type of operators: some_long_and_hairy_lvalue += 2; is better than: some_long_and_hairy_lvalue = some_long_and_hairy_lvalue + 2; Of course, since this subterfuge is especially convultuted and hairy, I would reccommend: e = some_long_and_hairy_expression; if (a == b) c = e; else d = e; Here, it is clear that either c or d are to be assigned to the same expression in either case. A good compiler will put the value in a temporary anyway. -- Stephen Carlson | ICL OFFICEPOWER Center scc@rlgvax.opcr.icl.com | 11490 Commerce Park Drive ..!uunet!rlgvax!scc | Reston, VA 22091
volpe@camelback.crd.ge.com (Christopher R Volpe) (02/15/91)
In article <11129@pasteur.Berkeley.EDU>, johnm@cory.Berkeley.EDU (John D. Mitchell) writes: |>In article <16754@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes: |>[....] |>>Yes, it's ugly, but it's conceivable that someone might have a good |>>reason for defining a macro to do this, so that the macro may be used |>>in an expression context. |> |>Aahhh! But context *is* everything. Huh??? So, like, what's your point? |> |>One reason to use macros is to hide this sort of cryptic code behind |>a nice facade. Oh well... if only C had... :-) Isn't that what I suggested? Again, I'm unclear as to what you're trying to say. Are you agreeing? Disagreeing? And what is it that you wish C had? |> |>---- John D. Mitchell |> johnm@cory.Berkeley.EDU ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
rmartin@clear.com (Bob Martin) (02/15/91)
In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >I'm wondering if anyone has any comments on using: > > *(a==b?&c:&d) = 1; > >instead of: > > if (a==b) c=1; > else d=1; > >thanks, burkhard burow%13313.hepnet@csa3.lbl.gov Burkhard: There are a number of disadvantages to the first case above. I will discuss the least important ones first. 1. It probably generates more code. The pointer operations will force the poor compiler to generate pointer references and dereferences. 2. It wont work if c or d happen to be register variables. 3. It wont work if c and d are of different types. (i.e. int c; double d;) 4. It is cryptic. In general it is not true that code gets better if you remove whitespace, or use clever little tricks. With a few notable exceptions, the most important feature of code (other than that it should work) is that it should be easy to read and understand. Unless you are horribly pressed for execution speed or memory space, you should be willing to make concessions to these goals for the goal of readability. -- +-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for | | rmartin@clear.com |:R::R:C::::M:M:M:M:| my words but me. I want | | uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all | +----------------------+:R::R::CCC:M:::::M:| the blame. So there. |
michi@ptcburp.ptcbu.oz.au (Michael Henning) (02/15/91)
burow@cernvax.cern.ch (burkhard burow) writes: >I'm wondering if anyone has any comments on using: > *(a==b?&c:&d) = 1; >instead of: > if (a==b) c=1; > else d=1; Yes, I do :-) If you compare the two above statements, the answer should be obvious. The second expression is perfectly clear and readable, whereas the first one takes some looking at to decipher. Besides, on many compilers, the first expression will take longer to run, since you are dereferencing a pointer there. Michi. -- -m------- Michael Henning +61 75 950255 ---mmm----- Pyramid Technology +61 75 522475 FAX -----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au -------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
johnm@cory.Berkeley.EDU (John D. Mitchell) (02/15/91)
In article <16782@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes: >In article <11129@pasteur.Berkeley.EDU>, johnm@cory.Berkeley.EDU (John >D. Mitchell) writes: >|>In article <16754@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com >(Christopher R Volpe) writes: >|>[....] >|>>Yes, it's ugly, but it's conceivable that someone might have a good >|>>reason for defining a macro to do this, so that the macro may be used >|>>in an expression context. >|> >|>Aahhh! But context *is* everything. >Huh??? So, like, what's your point? Context: the parts just before and after a word or passage, that determines its meaning. (Webster's New World) In other words, the original poster gave a code snippet without any supporting context. That leaves the meaning up to the reader. I for one assumed that he was talking about using it in 'normal' code (macros being *not* normal :-). >|>One reason to use macros is to hide this sort of cryptic code behind >|>a nice facade. Oh well... if only C had... :-) >Isn't that what I suggested? Again, I'm unclear as to what you're trying >to say. Are you agreeing? Disagreeing? And what is it that you wish C had? Yep, I agree that due to whatever reasons the C language proper and its attendant pre-processor make the expression of some kinds of functionality cryptic, difficult, unreadable, confusing, etc. The ternary operator was built for its ability to be used inside the macro facility of a weak pre-processor. My "Oh well..." comment was a facetious attempt to jest those who always want 'just one more feature'. Sorry for the wasted net-width, John D. Mitchell johnm@cory.Berkeley.EDU
kers@hplb.hpl.hp.com (Chris Dollin) (02/15/91)
Someone (I've lost the attribution) asked how people felt about: > *(a==b?&c:&d) = 1; > >instead of: > > if (a==b) c=1; > else d=1; I'll add my agreement; the first one is "Ugh". But .. how would people feel if conditionals could deliver lvalues, ie, so that (a == b ? c : d) = 1; was legal and had the obvious meaning? (Clearly, when c, d, and especially 1 are more complex expressions, you might wish to make it abundantly clear that a *single* value was being assigned to one or other localtion.) If anyone sees fit to respond to this, I suggest they switch newsgroups to comp.lang.misc, as it will no longer be much to do with C ... -- Regards, Kers. | "You're better off not dreaming of the things to come; Caravan: | Dreams are always ending far too soon."
jon@maui.cs.ucla.edu (Jonathan Gingerich) (02/16/91)
burow@cernvax.cern.ch (burkhard burow) writes: > > I'm wondering if anyone has any comments on using: > > *(a==b?&c:&d) = 1; > > instead of: > > if (a==b) c=1; > else d=1; Yeah, you should use meaningful names even for shortlived variables. It seems very unlikely that a, b, c, and d would convey anything in context. Jon. P.S. Why not (a==b?c=1:(d=1)) ?
rh@smds.UUCP (Richard Harter) (02/16/91)
In article <15184@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes: > In article <11073@pasteur.Berkeley.EDU>, johnm@cory.Berkeley.EDU (John D. Mitchell) writes: > - In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: > - >I'm wondering if anyone has any comments on using: > - > *(a==b?&c:&d) = 1; > - >instead of: > - > if (a==b) c=1; > - > else d=1; > My comment was going to be that it sucked bigtime. However, I'll > buy "ugh" as a suitable comment too. > - P.S. No wonder people complain about the denseness of C code! > C code has nothing to do with it, more like the density of some coders. But Doug, isn't it one of the unwritten rules of C coding that the number of special characters be greater than the number of alphanumeric characters? :-) Seriously, there is a germ of a good idea here. The example is inane, but consider *(a==b?&c:&d) = <some complicated messy expression> One really doesn't want to code in said messy expression twice, so one tends to write something like temp = <some complicated messy expression> if (a==b) c = temp; else d = temp; Again this is more readable (and mainatainable). However the ugly one liner is better code in the sense of not having replications of a single term or in using temporaries. To be honest this is a trick I would have never thought of and would never use in C. In principle the idea is a good one but the C conditional expression is just too darned ugly. -- Richard Harter, Software Maintenance and Development Systems, Inc. Net address: jjmhome!smds!rh Phone: 508-369-7398 US Mail: SMDS Inc., PO Box 555, Concord MA 01742 This sentence no verb. This sentence short. This signature done.
throopw@sheol.UUCP (Wayne Throop) (02/16/91)
- gwyn@smoke.brl.mil (Doug Gwyn) -- rh@smds.UUCP (Richard Harter) -- [.. some context restored ..] -- *(a==b?&c:&d) = <some complicated messy expression> -- However the ugly one liner is better code in the sense of not having -- replications of a single term or in using temporaries. [...] In -- principle the idea is a good one but the C conditional expression is -- just too darned ugly. - There are good ways of exploiting the ?: operator and bad ways. - The example being discussed is clearly among the latter. I'm not sure I understand. Could either Doug or Richard expand a little on just why the expression is "ugly" or a "bad way" to exploit the conditional operator? It doesn't seem any worse than, say foo[a==b?c:d] = something; or even just foo[(a+b)*(c+d)] = something; or the like. All are examples of a complicated decision going into exactly which object is going to be assigned to. Granted, the conditional is more extreme than the subscripting examples, but not to any large degree IMHO. So why is the explicit conditional any worse than the others? ( Note: the restored context above may have obliterated the "example being discussed" by Doug. If the example I left there isn't the one he means, forgive me. ) -- Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org
dcl@ncsc1.ATT.COM (Dave Love) (02/17/91)
In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >I'm wondering if anyone has any comments on using: > *(a==b?&c:&d) = 1; Fine. As long as I never have to maintain your code. >thanks, burkhard burow%13313.hepnet@csa3.lbl.gov -- Dave Love UUCP: dcl@ncsc1.att.com CI$: 75126,2223 bix: dlove -- "MS-DOS... The ultimate PC virus." --
gwyn@smoke.brl.mil (Doug Gwyn) (02/17/91)
In article <326@smds.UUCP> rh@smds.UUCP (Richard Harter) writes: >> - > *(a==b?&c:&d) = 1; >Seriously, there is a germ of a good idea here. There are good ways of exploiting the ?: operator and bad ways. The example being discussed is clearly among the latter.
steve@taumet.com (Stephen Clamage) (02/17/91)
kers@hplb.hpl.hp.com (Chris Dollin) writes: >.. how would people feel if conditionals could deliver lvalues, ie, so that > (a == b ? c : d) = 1; >was legal and had the obvious meaning? As has been pointed out before, this is an extension to Gnu C. The expression is also legal C++, as long as c and d are both lvalues and have the same type (although not all compilers yet implement this feature). -- Steve Clamage, TauMetric Corp, steve@taumet.com
gwyn@smoke.brl.mil (Doug Gwyn) (02/18/91)
In article <1196@sheol.UUCP> throopw@sheol.UUCP (Wayne Throop) writes: >-- [.. some context restored ..] >-- *(a==b?&c:&d) = <some complicated messy expression> >- There are good ways of exploiting the ?: operator and bad ways. >- The example being discussed is clearly among the latter. >I'm not sure I understand. Could either Doug or Richard expand a little >on just why the expression is "ugly" or a "bad way" to exploit the >conditional operator? You mis-restored the context. The original example did NOT assign the value of "some complicated messy expression"; rather, it assigned the integer constant 1. It is an abuse of the potential utility of the ?: operator to use it, especially with the addition of levels of indirection, where a simple if ( a == b ) c = 1; else d = 1; would be much clearer and (assuming a decent compiler) at least as efficient. I doubt that efficiency should have been an issue anyway; however, clarity is very important. If you doubt that, some remedial reading of software engineering classics is indicated.
throopw@sheol.UUCP (Wayne Throop) (02/18/91)
> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) > I'd write [..multi-line if statements instead of > cryptic one-liners involving ?: ..] So would I, 99 and 44 one-hundreths percent of the time. And the remaining .56 percent of the time wouldn't be for reasons of "efficency" or to "get close to the machine" or any such secondary goal. As Dan points out, such things are unlikely to win over the good ol' if-then-else. And yet... every now and then, one naturally thinks of a situation as assigning (or incrementing, or tweaking, or whatever) "the appropriate one of" a set of lvalues. Now, most often this is modeled as assignment to an array. But every once in a blue moon, the lvalues are not related by membership in an array, nor by anything much in particular beyond their participation in being one of the set of "appropriate ones" to assign something to. In such a rare case, I'd 'druther code the way I think about it, and think about it the way I code it.... that is, I'd really rather model it as a single assignment to a peculiar lvalue. So while I tend to agree that ?: in lhs expressions are, as a statistical tendency, an abomination, I can't agree that this is because of anything wrong with the idea in itself... just that the application's rightful place is very rare. The moral is (again): code like you think, think like you code. ( I hope this moral is thought provoking but essentially uncontroversial, but one never knows... ) -- Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org
throopw@sheol.UUCP (Wayne Throop) (02/18/91)
> rh@smds.UUCP (Richard Harter) [.. discussing assignment to expressions like *(a==b?&c:&d) ..] > First of all the trick of using > *(cond?&var1:&var2) is not technically legal since the result of the > ?: is not an lvalue. [Harbison & Steele]. I rather suspect you could > sneak it past most compilers though. Well... I'd say "all correct C compilers" really ought to be "most", wouldn't you? As Dan Bernstein has pointed out in another article, Richard is incorrect here. While it is true that the result of ?: is never an lvalue, this is irrelevant since the result of * always is. > Secondly the syntax of the condition is, in its own right, ugly. No uglier than much else of C's alphabet soup operators, I'd say. > Thirdly, the use of the conditional in an lvalue obscures the destination > of an assignment. I agree, but this is appropriate if the destination is, in fact, obscure or arcane. That is, I agree it is something to be avoided, but I think it may sometimes be the least of the available evils. > Fourthly, the ?: is hard to read (see second complaint above). Again, I agree with the same reservation as in "thirdly" above. > Fifthly, the original example is an instance of making code less efficient > in the process of reducing the number of statements since you have to > reference and dereference. It's a pretty poor compiler that would be confused by this into doing something noticeably inefficent. On the other hand, I think it is Morally Wrong to invoke extraneous operations. (And even if I'm a little vague on what can be classed as extraneous, I would be perverse not to include the address-of operation in the example under discussion as extraneous.) Keep in mind: I agree that ?: is not well suited for the LHS of expressions... I was just overreacting to what I perceived as an oversimple blanket condemnation. (Before chastizing me on grounds that this is all in my mind, realize that I KNOW that... but taking what has been said as a blanket condemnation is an error worth warning folks against, isn't it? Well... isn't it?) -- Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org
rh@smds.UUCP (Richard Harter) (02/18/91)
In article <15227@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes: > In article <326@smds.UUCP> rh@smds.UUCP (Richard Harter) writes: > >> - > *(a==b?&c:&d) = 1; > >Seriously, there is a germ of a good idea here. > There are good ways of exploiting the ?: operator and bad ways. > The example being discussed is clearly among the latter. I agree that the example is a bad idea -- of using the ?: operator in C. For that matter the ?: operator is one of the uglier things in C. What the chap was doing was emulating a feature that is not in C or in most other languages, i.e. selected assignment. The idea is interesting although I am not sure it is worthwhile. For example you can do something like this is in C: static int a,b,c,d; static int *index[4] = {&a,&b,&c,&d}; .... *index[i] = some-expression; which is a round-about way of saying "set the i'th item in the list a,b,c,d to 'some-expression'". The point is that the example is an attempt to do something which C does not provide a natural way of doing. -- Richard Harter, Software Maintenance and Development Systems, Inc. Net address: jjmhome!smds!rh Phone: 508-369-7398 US Mail: SMDS Inc., PO Box 555, Concord MA 01742 This sentence no verb. This sentence short. This signature done.
rh@smds.UUCP (Richard Harter) (02/18/91)
In article <1196@sheol.UUCP>, throopw@sheol.UUCP (Wayne Throop) writes: > - gwyn@smoke.brl.mil (Doug Gwyn) > -- rh@smds.UUCP (Richard Harter) > > -- [.. some context restored ..] > -- *(a==b?&c:&d) = <some complicated messy expression> > -- However the ugly one liner is better code in the sense of not having > -- replications of a single term or in using temporaries. [...] In > -- principle the idea is a good one but the C conditional expression is > -- just too darned ugly. > - There are good ways of exploiting the ?: operator and bad ways. > - The example being discussed is clearly among the latter. As Doug points out in another message the original had 1. instead of a complex expression. > I'm not sure I understand. Could either Doug or Richard expand a little > on just why the expression is "ugly" or a "bad way" to exploit the > conditional operator? It doesn't seem any worse than, say > foo[a==b?c:d] = something; > or even just > foo[(a+b)*(c+d)] = something; > or the like. All are examples of a complicated decision going into > exactly which object is going to be assigned to. Granted, the > conditional is more extreme than the subscripting examples, but not to > any large degree IMHO. So why is the explicit conditional any worse > than the others? Let's run down the line on this. First of all the trick of using *(cond?&var1:&var2) is not technically legal since the result of the ?: is not an lvalue. [Harbison & Steele]. I rather suspect you could sneak it past most compilers though. However by doing so you are are violating the specs and the intent of the language [for what that's worth.] Secondly the syntax of the condition is, in its own right, ugly. This is a personal opinion, but it is seconded by some noted practioners of the art. Why is it ugly? It is ugly because it has special rules and syntax that do not fit the rest of the language. C is (despite the complaints) actually a fairly elegant and well designed language. The syntax is quite regular. The conditional uses special symbols in a way that is not very consistent with the rest of the language. Call this an esthetic objection if you like. Thirdly, the use of the conditional in an lvalue obscures the destination of an assignment. This is equally true whether you write *(a==b?&x:&y) = expression; /* ugh */ or f[a==b?i:j] = expression; /* not quite as bad */ If you are reading the code it is less than obvious what is being set. Fourthly, the ?: is hard to read (see second complaint above). It is particularly hard to read when it is used as a sub expression. Let me give an example, with apologies to Rich Salz: /* This next line requires a good C compiler. */ if (*p == '-' ? *text <= *++p && *text >= last : *text == *p) matched = TRUE; Fifthly, the original example is an instance of making code less efficient in the process of reducing the number of statements since you have to reference and dereference. In the old days beginning programmers had to learn the hard way that clever tricks to reduce the number of lines of code often lead to code that took longer to execute. Having said all these nasty things, are there any reasons why one would use the conditional? One can do without it -- I wrote C for five years before I used my first conditional. One reason, which several people have mentioned, is that it facilitates macro writing. Another is that it does, in fact, solve a real problem. There really is a need for conditional expressions. -- Richard Harter, Software Maintenance and Development Systems, Inc. Net address: jjmhome!smds!rh Phone: 508-369-7398 US Mail: SMDS Inc., PO Box 555, Concord MA 01742 This sentence no verb. This sentence short. This signature done.
hugh@fivegl.co.nz (Hugh Grierson) (02/18/91)
In article <1991Feb13.223412.28254@grebyn.com> ckp@grebyn.com (Checkpoint Technologies) writes: >In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >>I'm wondering if anyone has any comments on using: >> >> *(a==b?&c:&d) = 1; [general Ugh comments...] >The only time I would use the first form is in a macro, in a situation >where I really wanted an expression rather than a statement. But that's >all. Even then it would be better to use... #define cord(a,b,c,d) (a==b?c=1:d=1) -- Hugh Grierson hugh@fivegl.co.nz | Perfection is attained not when there is 5GL International Ltd, | no more that can be added, but when there Auckland, New Zealand | is no more that can be taken away.
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (02/18/91)
In article <331@smds.UUCP> rh@smds.UUCP (Richard Harter) writes: > Let's run down the line on this. First of all the trick of using > *(cond?&var1:&var2) is not technically legal since the result of the > ?: is not an lvalue. Say what? It doesn't matter whether foobiebletch is an lvalue as long as nobody tries to assign a value to it. Here foobiebletch is a (non-const) pointer type, so *foobiebletch is an lvalue, and *foobiebletch = x is fine. > Secondly the syntax of the condition is, in its own right, ugly. Yes. I'd write either { register glorp *addr; if (cond) addr = &var1; else addr = &var2; *addr = expr; } or { register glorp temp; temp = expr; if (cond) var1 = temp; else var2 = temp; } if any of the expressions involved were particularly complex. How else would the machine do the job anyway? > There really is a need for > conditional expressions. This can be argued. ?: is almost purely syntactic; I don't know any machine that will optimize a ?: expression better than an equivalent if-then. Its syntactic benefits are minimal at best. ---Dan
throop@aurs01.UUCP (Wayne Throop) (02/19/91)
> gwyn@smoke.brl.mil (Doug Gwyn) [.. discussing *(a==b?&c:&d) = 1 ..] > It is an abuse of the potential utility of the ?: operator to use it, > especially with the addition of levels of indirection, where a simple > if ( a == b ) c = 1; else d = 1; > would be much clearer [...] clarity is very important. I agree strongly about the general principle of clarity. But I suspect I may differ in the question of what is clear. To start with agreement, I agree about the extra levels of indirection being unclear. For example, *(color==BLUE? &blue_items : &nonblue_items) += 1; is more messy (and less to be prefered) than if( color==BLUE ) blue_items += 1; else nonblue_items += 1; Worse still, the former requires mumble_items to be addressable, when they conceptually only need to be lvalues. But on the other hand, I'd say that the GCC extension (color==BLUE ? blue_items : nonblue_items) += 1; is clearer than either, and something like *(color==BLUE ? blue_items_ref : nonblue_items_ref) += 1; seems perfectly clear to me, and (as a matter of taste) preferable to the use of an "if" statement (say, inside a routine which counts item colors as a side effect and is passed references to counts to fill in (uh... not that I'd tend to design a routine that way, but supposing someone did...)). Certainly (hmmm... better say "IMHO"), it isn't much less clear than item_count[color] += 1; Wayne Throop ...!mcnc!aurgate!throop
gwyn@smoke.brl.mil (Doug Gwyn) (02/19/91)
In article <5672:Feb1814:26:0291@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >> There really is a need for >> conditional expressions. >This can be argued. ?: is almost purely syntactic; ... Yes, but then so is the provision of a multiplicity of ways of expressing looping. I seldom have occasion to assign the same value to alternative variables, as in the example that started this thread, but often I need to assign alternative values to a given variable, or return alternative values from a function. Often it is both convenient and clear to use a ?: expression rather than cast the code into the form of an "if" statement.
drd@siia.mv.com (David Dick) (02/20/91)
In <326@smds.UUCP> rh@smds.UUCP (Richard Harter) writes: >In article <15184@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes: >> In article <11073@pasteur.Berkeley.EDU>, johnm@cory.Berkeley.EDU (John D. Mitchell) writes: >> - In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >> - >I'm wondering if anyone has any comments on using: >> - > *(a==b?&c:&d) = 1; >> - >instead of: >> - > if (a==b) c=1; >> - > else d=1; >Seriously, there is a germ of a good idea here. The example is inane, >but consider > *(a==b?&c:&d) = <some complicated messy expression> >One really doesn't want to code in said messy expression twice, so one >tends to write something like > temp = <some complicated messy expression> > if (a==b) c = temp; > else d = temp; I believe that the result of a conditional expression is explicitly defined to be an r-value, so that it cannot be assigned into. David Dick Software Innovations, Inc. [the Software Moving Company(sm)]
michi@ptcburp.ptcbu.oz.au (Michael Henning) (02/20/91)
throopw@sheol.UUCP (Wayne Throop) writes: >As Dan Bernstein has pointed out in another article, Richard is >incorrect here. While it is true that the result of ?: is never >an lvalue, this is irrelevant since the result of * always is. ^^^^^^^^^^^^^^^^^^^^^ Hmmm... What about int array[10][10]; and an expression *array The type of the expression after dereferencing is "array of 10 ints", which is *not* an lvalue. Michi. -- -m------- Michael Henning +61 75 950255 ---mmm----- Pyramid Technology +61 75 522475 FAX -----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au -------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
gwyn@smoke.brl.mil (Doug Gwyn) (02/20/91)
In article <59582@aurs01.UUCP> throop@aurs01.UUCP (Wayne Throop) writes: >> gwyn@smoke.brl.mil (Doug Gwyn) >> if ( a == b ) c = 1; else d = 1; Actually I would never recommend the one-line format that you compressed this to.
torek@elf.ee.lbl.gov (Chris Torek) (02/20/91)
>throopw@sheol.UUCP (Wayne Throop) writes: [the result of unary `*' (indirect) is always an lvalue] In article <335@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes [abbreviated]: > int array[10][10]; > *array >The type of the expression after dereferencing is "array of 10 ints", which >is *not* an lvalue. Technically, the result *is* an lvalue (according to ANSI terminology, at least)---but it is not a `modifiable' lvalue. (The type of `array' above is `array 10 of array 10 of int'; in a value context, such as the target of unary `*', this changes to `pointer to array 10 of int'. The indirection changes this it `array 10 of int', which, in an expression context, devolves to `pointer to int'. Until the final devolving, however, the object produced by the indirection is a non-modifiable lvalue of type `array 10 of int'.) -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
sarima@tdatirv.UUCP (Stanley Friesen) (02/21/91)
In article <335@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >throopw@sheol.UUCP (Wayne Throop) writes: >> this is irrelevant since the result of * always is [an lvalue]. ^^^^^^^^^^^^^^^^^^^^^ >What about >int array[10][10]; >and an expression > *array >The type of the expression after dereferencing is "array of 10 ints", which >is *not* an lvalue. Yes it is, at least according to the ANSI definition of lvalue. It is just not a *modifiable* lvalue. [Of course this is 'promoted' to a pointer to int in most contexts]. In fact the ANSI standard explicitely states that the result of the unary * operator is an lvalue (with *no* conditions). -- --------------- uunet!tdatirv!sarima (Stanley Friesen)
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (02/21/91)
In article <335@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: > int array[10][10]; > *array > The type of the expression after dereferencing is "array of 10 ints", which > is *not* an lvalue. Either (1) array types are never lvalues, or (2) array types can never be assigned to even if they are lvalues. I don't know which way the standard defines lvalues; I find (2) a simpler approach, but in any case (1) and (2) produce the same results. None of this is relevant to the question at hand, which is whether *(cond ? &a : &b) = x is valid. It is, provided that a = x and b = x are valid. It will work under any sane compiler. It must work under an ANSI compiler. ---Dan
al@unhd.unh.edu (Anthony Lapadula) (02/21/91)
In article <5669:Feb2020:23:4791@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: > >None of this is relevant to the question at hand, which is whether > > *(cond ? &a : &b) = x > >is valid. It is, provided that a = x and b = x are valid. It will work >under any sane compiler. It must work under an ANSI compiler. Not true. Consider int a; char b; int x; Certainly ``a = x'' and ``b = x'' are valid, but ``*(cond ? &a : &b) = x'' is not. -- Anthony (uunet!unhd!al, al@cs.unh.edu) Lapadula "I would agree with you if you were right." -- Dr Sayer, "Awakenings"
michi@ptcburp.ptcbu.oz.au (Michael Henning) (02/21/91)
torek@elf.ee.lbl.gov (Chris Torek) writes: >>throopw@sheol.UUCP (Wayne Throop) writes: >[the result of unary `*' (indirect) is always an lvalue] >In article <335@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au >(Michael Henning) writes [abbreviated]: >> int array[10][10]; >> *array >>The type of the expression after dereferencing is "array of 10 ints", which >>is *not* an lvalue. >Technically, the result *is* an lvalue (according to ANSI terminology, >at least)---but it is not a `modifiable' lvalue. >(The type of `array' above is `array 10 of array 10 of int'; in a value >context, such as the target of unary `*', this changes to `pointer to >array 10 of int'. The indirection changes this it `array 10 of int', >which, in an expression context, devolves to `pointer to int'. Until >the final devolving, however, the object produced by the indirection is >a non-modifiable lvalue of type `array 10 of int'.) Hmmm..., I'm confused now. From K & R: "An *object* is a manipulatable region of storage; an *lvalue* is an expression referring to an object. [...] There are operators which yield lvalues: for example, if E is an expression of pointer type, then *E is an lvalue expression referring to the object to which E points. The name "lvalue" comes from the assignment expression E1 = E2 in which the left operand E1 must be an lvalue expression." And further on, in the section about the * operator: "The unary * operator means indirection: the expression must be a pointer, and the result is an lvalue referring to the object to which the expression points. If the type of the expression is "pointer to ...", the type of the result is "..."." And in the section about the various assignment operators: " [...] All require an lvalue as their left operand, and the type of an assignment expression is that of its left operand. [...] " From Harbison & Steele: "An "lvalue" is an expression that refers to an object in such a way that the object may be altered as well as examined. [...] (An expression or result is called an lvalue because it may be used on the left-hand side of an assignment. [...] ) [...] An indirection expression *e is always an lvalue, regardless of whether e is an lvalue." Neither K & R nor Harbison & Steele make any distinction between modifiable and non-modifiable lvalues. Furthermore, both say that the result of applying a dereference operator to a pointer *always* yields an lvalue, and that the left operand of an assignment operator must be an lvalue. Yet, if "array" is a two dimensional array, then "*array", by definition, is an lvalue, but "*array" cannot appear on the left hand side of an assignment statement, since the usual unary conversions (conversion to a pointer in this case) do not take place for the left operand, and the type of the left operand is "array of 10 ints". I get the impression that there simply are some inconsistencies in the language definition. Either an object is an lvalue, in which case it can be used as the left operand of an assignment, or it isn't, in which case it cannot be used that way. I believe that the issue could be cleaned up by changing the definition of "*" to say something like The unary operator means indirection: the expression must be a pointer, and the result is an lvalue referring to the object to which the expression points, except if the object is an array. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Something to that effect should clean things up. Any comments anyone ? Michi. -- -m------- Michael Henning +61 75 950255 ---mmm----- Pyramid Technology +61 75 522475 FAX -----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au -------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (02/21/91)
In article <1991Feb20.215402.16343@unhd.unh.edu> al@unhd.unh.edu (Anthony Lapadula) writes: > In article <5669:Feb2020:23:4791@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: > >None of this is relevant to the question at hand, which is whether > > *(cond ? &a : &b) = x > >is valid. It is, provided that a = x and b = x are valid. It will work > >under any sane compiler. It must work under an ANSI compiler. > Not true. Oops, sorry. Make that ``a and b have the same type and a = x is valid.'' ---Dan
torek@elf.ee.lbl.gov (Chris Torek) (02/21/91)
>>In article <335@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au >>(Michael Henning) writes [abbreviated]: >>> int array[10][10]; >>> *array >>>The type of the expression after dereferencing is "array of 10 ints", which >>>is *not* an lvalue. >In article <10069@dog.ee.lbl.gov> I wrote: >>Technically, the result *is* an lvalue (according to ANSI terminology, >>at least)---but it is not a `modifiable' lvalue. In article <337@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >Hmmm..., I'm confused now. [quotes K&R and H&S] >Neither K & R nor Harbison & Steele make any distinction between modifiable >and non-modifiable lvalues. Two points: a) both K&R and H&S exist in multiple editions (and K&R 2, at least, exists in several versions; later printings have some minor fixes). b) Neither K&R nor H&S claim to be the ANSI C standard. For that you must obtain X3.159-1989 from your local ANSI distributor. The introduction of `modifiable' and `nonmodifiable' lvalues is new in ANSI C; something like it is needed to make sense of `const int x = 3', in which x is an lvalue but may not be assigned-to. -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
sarima@tdatirv.UUCP (Stanley Friesen) (02/22/91)
In article <337@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: |Hmmm..., I'm confused now. From K & R: | |"An *object* is a manipulatable region of storage; an *lvalue* is an expression |referring to an object. [...] ... |From Harbison & Steele: | |"An "lvalue" is an expression that refers to an object in such a way that the |object may be altered as well as examined. [...] ... Note that these definitions are *different*. The K&R definition does *not* imply that an lvalue may be used on the left hand side of an assignment. |Neither K & R nor Harbison & Steele make any distinction between modifiable |and non-modifiable lvalues. Furthermore, both say that the result of |applying a dereference operator to a pointer *always* yields an lvalue, |and that the left operand of an assignment operator must be an lvalue. |Yet, if "array" is a two dimensional array, then "*array", by definition, is |an lvalue, but "*array" cannot appear on the left hand side of an assignment |statement, since the usual unary conversions (conversion to a pointer in this |case) do not take place for the left operand, and the type of the left |operand is "array of 10 ints". |I get the impression that there simply are some inconsistencies in the |language definition. Quite correct. The definitions and constraints as presented in the non-ANSI texts are *inconsistant*! This is why the ANSI committee decided to clarify the matter. They chose to use the K&R definition of lvalue, and to revise the constraint on assignment operators to require a *modifiable* lvalue as the left operand. They chose this approach largely because it simplified the semantics of the 'const' qualifier - a 'const' expression can simply be described as one that refers to an object that cannot be modified. Now both the restriction against assignment to arrays and the proper restrictions on the use of 'const' entities are captured in a single constraint on assignments and a single definition (of 'modifiable lvalue'). This also allowed the C standard to retain the simple rule that a dereference *always* yields an lvalue. |Either an object is an lvalue, in which case it can |be used as the left operand of an assignment, or it isn't, in which case |it cannot be used that way. I believe that the issue could be cleaned up |by changing the definition of "*" to say something like ... |Something to that effect should clean things up. Any comments anyone ? Except that the ANSI committee has already cleaned things up the other way, and with less complexity - since non-modifiable lvalues are the best way to handle 'const' anyway. [Trying to say that a 'const' variable does not yield an lvalue leads to a very complex definition for lvalue]. -- --------------- uunet!tdatirv!sarima (Stanley Friesen)
gwyn@smoke.brl.mil (Doug Gwyn) (02/22/91)
In article <337@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes: >Something to that effect should clean things up. Any comments anyone ? Yeah -- get hold of a copy of the C standard, which has already straightened this matter out.
s900387@minyos.xx.rmit.oz.au (Craig Macbride) (02/23/91)
johnm@cory.Berkeley.EDU (John D. Mitchell) writes: >In article <4155@cernvax.cern.ch> burow@cernvax.cern.ch (burkhard burow) writes: >>I'm wondering if anyone has any comments on using: >> *(a==b?&c:&d) = 1; >>instead of: >> if (a==b) c=1; >> else d=1; >1) Readability, readability, READABILITY! >2) Why? It's not any faster. 3) If someone decides to make c and/or d register variables, they have to decipher and change your cryptic piece of assignment code. -- _____________________________________________________________________________ | Craig Macbride, s900387@minyos.xx.rmit.oz.au | Reality is for people who | | Only the equipment belongs to Victoria Uni. | can't handle science fiction.| | of Technology (RMIT); The opinions are mine. |______________________________|
rh@smds.UUCP (Richard Harter) (02/23/91)
In article <1210@sheol.UUCP>, throopw@sheol.UUCP (Wayne Throop) writes: > > rh@smds.UUCP (Richard Harter) > [.. discussing assignment to expressions like *(a==b?&c:&d) ..] > > First of all the trick of using > > *(cond?&var1:&var2) is not technically legal since the result of the > > ?: is not an lvalue. [Harbison & Steele]. I rather suspect you could > > sneak it past most compilers though. > As Dan Bernstein has pointed out in another article, Richard is > incorrect here. While it is true that the result of ?: is never > an lvalue, this is irrelevant since the result of * always is. Mea culpa, remove foot from mouth, etc. Actually, as other articles have pointed out there are some fine points, depending on whether you are talking about paleolithic C, neo-modern classic C, or ANSI C. However the cited remark was a bit of all wrong. As far as the ?: syntax is concerned I would like to reiterate the point that it is dissimilar to other C constructs (other than that it uses still more special symbols.) All other operators which use punctuation (with the exception of ->) are either unary or binary operators. All conditional operations, except for ?:, use words, e.g. if, else, while, etc. It is a wart. -- Richard Harter, Software Maintenance and Development Systems, Inc. Net address: jjmhome!smds!rh Phone: 508-369-7398 US Mail: SMDS Inc., PO Box 555, Concord MA 01742 This sentence no verb. This sentence short. This signature done.