- **C Programming**
(*http://www.velocityreviews.com/forums/f42-c-programming.html*)

- - **In how many ways should this fail?**
(*http://www.velocityreviews.com/forums/t867708-in-how-many-ways-should-this-fail.html*)

In how many ways should this fail?At work, we got into a talk about weird C constructs. One of my collegues volunteered this line: (a>b)?a:b = 42; According to him, he have found three different compilers with three different ways of handling this. One did nothing, one always assigned to b, and the last one did what one should expect, were it legal. We ended up discussing what the acutal problem here is. The diffrerent compilers we had at hand gave different diagnostics, so they giv no clue. We narrowed it down to one of two: 1) a and b are not lvalues in this context. 2) This expression invokes undefined behaviour, since there are no sequence point between (a>b) and the assignment. -- /Wegge Leder efter redundant peering af dk.*,linux.debian.* |

Re: In how many ways should this fail?On 01/30/2012 10:32 AM, Anders Wegge Keller wrote:
> > At work, we got into a talk about weird C constructs. One of my > collegues volunteered this line: > > (a>b)?a:b = 42; > > According to him, he have found three different compilers with three > different ways of handling this. One did nothing, one always assigned > to b, and the last one did what one should expect, were it legal. > > We ended up discussing what the acutal problem here is. The > diffrerent compilers we had at hand gave different diagnostics, so > they giv no clue. We narrowed it down to one of two: > > 1) a and b are not lvalues in this context. That's true, but not relevant. The key issue is that the C standard fails to specify that it's an lvalue - but to make it clear that this wasn't an oversight, footnote 95 says "A conditional expression does not yield an lvalue." As a result, its result cannot be assigned to. Note that this is one of the differences between C and C++; the result of a ?: expression is an lvalue in C++. > 2) This expression invokes undefined behaviour, since there are no > sequence point between (a>b) and the assignment. 6.5.15 "Conditional operator" p4: "The first operand is evaluated; there is a sequence point after its evaluation." Since you need to evaluate the ?: expression to determine what should be assigned to; there is indeed a sequence point between the evaluation of the > operation and the assignment. If you'd avoided the other problem by writing *((a>b)?&a : &b) = 42; there would not have been a problem. |

Re: In how many ways should this fail?On 01/30/2012 11:07 AM, James Kuyper wrote:
> On 01/30/2012 10:32 AM, Anders Wegge Keller wrote: >> >> At work, we got into a talk about weird C constructs. One of my >> collegues volunteered this line: >> >> (a>b)?a:b = 42; .... >> 1) a and b are not lvalues in this context. > > That's true, but not relevant. The key issue is that the C standard > fails to specify that it's an lvalue In the course of editing that sentence, I accidentally removed the thing that "it" refers to. That sentence should have said: "The key issue is that the C standard fails to specify that the result of a conditional expression is an lvalue." |

Re: In how many ways should this fail?On Jan 30, 3:32*pm, Anders Wegge Keller <we...@wegge.dk> wrote:
> *According to him, he have found three different compilers with three > different ways of handling this. One did nothing, one always assigned > to b, and the last one did what one should expect, were it legal. What should one expect? (a>b) ? a : (b=42); In C (given that [foo() ? a : b] isn't an lvalue), that seems a perfectly sensible parse to me. One might even do x = ((a>b) ? a : (b=42)); as a truly horrible way of writing if(a>b) { x = a; } else { x = b = 42; } In C++, obviously (a > b ? a : b) = 42; is a reasonable parse. As ever, anyone who fails to use enough parenthesis to unambiguously express intent, needs a good hard slap. |

Re: In how many ways should this fail?"Devil with the China Blue Dress" <chine.bleu@yahoo.com> wrote in message news:chine.bleu-61D2CA.08302730012012@news.eternal-september.org... > In article <87hazdcikg.fsf@huddi.jernurt.dk>, > Anders Wegge Keller <wegge@wegge.dk> wrote: > >> At work, we got into a talk about weird C constructs. One of my >> collegues volunteered this line: >> >> (a>b)?a:b = 42; > > *(a>b ? &a : &b) = 42; There's no reason why the original version shouldn't work. Doing as you suggest is a bit like writing: *(&a) = 42; instead of a = 42. It shouldn't be necessary and it's less readable. -- Bartc |

Re: In how many ways should this fail?On 1/30/2012 10:32 AM, Anders Wegge Keller wrote:
> > At work, we got into a talk about weird C constructs. One of my > collegues volunteered this line: > > (a>b)?a:b = 42; > > According to him, he have found three different compilers with three > different ways of handling this. One did nothing, one always assigned > to b, and the last one did what one should expect, were it legal. > > We ended up discussing what the acutal problem here is. The > diffrerent compilers we had at hand gave different diagnostics, so > they giv no clue. We narrowed it down to one of two: > > 1) a and b are not lvalues in this context. > > 2) This expression invokes undefined behaviour, since there are no > sequence point between (a>b) and the assignment. > > > You may require additional parentheses to use this extension more reliably (and force diagnostics when it is interpreted as a do-nothing): ((a>b)?a:b) = 42; Under compilers which support this extension, you would need to set standards checking options to reject it and get a complaint. Other compilers I have used will reject it with a diagnostic. -- Tim Prince |

Re: In how many ways should this fail?On 2012-01-30, Anders Wegge Keller <wegge@wegge.dk> wrote:
> > At work, we got into a talk about weird C constructs. One of my > collegues volunteered this line: > > (a>b)?a:b = 42; > > According to him, he have found three different compilers with three > different ways of handling this. Some compilers accept a nonstandard dialect with extensions by default and have to be told to interpret the input language as ISO C. In the GNU C dialect, it is possible assign "through" the ternary operator. In the C++ dialect of C, you can do this also, so if you compile code as either C or C++, you may run into this working under C++, but then breaking when someone runs the C build. ISO C does not have this feature: the result of A ? B : C is not an lvalue. Very recent case in point: http://www.kylheku.com/cgit/txr/comm...34c51f17936df6 > We ended up discussing what the acutal problem here is. Probably, that of not knowing that there exist different dialects of C, and that your compiler might not be using the one you think it is. |

Re: In how many ways should this fail?On 2012-01-30, BartC <bc@freeuk.com> wrote:
> > > "Devil with the China Blue Dress" <chine.bleu@yahoo.com> wrote in message > news:chine.bleu-61D2CA.08302730012012@news.eternal-september.org... >> In article <87hazdcikg.fsf@huddi.jernurt.dk>, >> Anders Wegge Keller <wegge@wegge.dk> wrote: >> >>> At work, we got into a talk about weird C constructs. One of my >>> collegues volunteered this line: >>> >>> (a>b)?a:b = 42; >> >> *(a>b ? &a : &b) = 42; > > There's no reason why the original version shouldn't work. Doing as you > suggest is a bit like writing: > > *(&a) = 42; > > instead of a = 42. It shouldn't be necessary and it's less readable. It isn't necessary in the "better C" known as C++. Why not use that? Ah right, portability. The *(a>b ? &a : &b) = 42; method works in both C and C++. The ternary syntax is awful anyway. Any time you nest it or combine it with adjacent operators it becomes hard to decipher the precedence. A function-like syntax both problems: #define IF(a,b,c) ((a) ? (b) : (c))) #define IFL(a,b,c) (*((a) ? &(b) : &(c))) IFL(foo != bar(), a, b[i]) = x | FLAG; |

Re: In how many ways should this fail?On 01/30/2012 11:43 AM, BartC wrote:
> > > "Devil with the China Blue Dress" <chine.bleu@yahoo.com> wrote in message > news:chine.bleu-61D2CA.08302730012012@news.eternal-september.org... >> In article <87hazdcikg.fsf@huddi.jernurt.dk>, >> Anders Wegge Keller <wegge@wegge.dk> wrote: >> >>> At work, we got into a talk about weird C constructs. One of my >>> collegues volunteered this line: >>> >>> (a>b)?a:b = 42; >> >> *(a>b ? &a : &b) = 42; > > There's no reason why the original version shouldn't work. ... That depends upon what you mean by "work". The original expression is equivalent to b = 42; Which is unlikely to be what the author intended, and would be a pretty bizarre way of writing it if that was what he intended. Assuming that the parentheses needed to force the intended parse are inserted, there's still the problem that ((a>b)?a:b) isn't an lvalue. > ... Doing as you > suggest is a bit like writing: > > *(&a) = 42; > > instead of a = 42. ... There's one key difference: *((a>b) ? &a : &b) = 42 is necessary in C, *(&a) = 42 is not. > ... It shouldn't be necessary and it's less readable. You're arguably correct about that. C++ allows the original expression to work as intended, even though C does not. This is because the C++ grammar differs from the C grammar by not allowing the third operand to be an assignment expression, and the C++ standard specifies that the result is an lvalue. They made the change because it makes some things involving C++ classes are more convenient; but the fact that it has been done is C++ means it could be done in C - that fact doesn't depend upon any C++-specific features. |

Re: In how many ways should this fail?gwowen <gwowen@gmail.com> writes:
> On Jan 30, 3:32Â*pm, Anders Wegge Keller <we...@wegge.dk> wrote: > >> Â*According to him, he have found three different compilers with three >> different ways of handling this. One did nothing, one always assigned >> to b, and the last one did what one should expect, were it legal. <talking about:> a > b ? a : b = 42; > What should one expect? > > (a>b) ? a : (b=42); > > In C (given that [foo() ? a : b] isn't an lvalue), that seems a > perfectly sensible parse to me. It might be sensible, but it's no what C's syntax mandates. A conforming compiler must parse it as ((a > b) ? a : b) = 42; <snip> > In C++, obviously > (a > b ? a : b) = 42; > is a reasonable parse. Again, it's reasonable... but wrong. The original expression must parse as (a > b) ? a : (b = 42); The differences between C and C++ here are two-fold: not only can a conditional expression be an l-value, but the syntax is also different. An assignment is valid after the ':' in C++ but not in C. Lots of operator precedence tables that claim be for "C/C++" get this wrong. > As ever, anyone who fails to use enough parenthesis to unambiguously > express intent, needs a good hard slap. Particularly in this case! -- Ben. |

All times are GMT. The time now is 05:13 AM. |

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.

SEO by vBSEO ©2010, Crawlability, Inc.