# Side effects in conditional expressions

Discussion in 'C Programming' started by August Karlstrom, Oct 1, 2010.

1. ### August KarlstromGuest

Among C programmers it is not uncommon to use expressions with
side-effects such as `y++' in the statement `x = y++;'. If we look at a
statement like

(x == 0)? x++: y *= 2;

/August

--
The competent programmer is fully aware of the limited size of his own
skull. He therefore approaches his task with full humility, and avoids
clever tricks like the plague. --Edsger Dijkstra

August Karlstrom, Oct 1, 2010

2. ### Chïna Blüe Öyster CultGuest

In article <i85kc7\$mcj\$>,
August Karlstrom <> wrote:

> (x == 0)? x++: y *= 2;
>

Can you guarentee what will be assigned to what if x==0 or x==1? If not, you

Also x++ is a rvalue, not an lvalue, so even if ?: has been extended to lvalues,
this won't work.

--
Damn the living - It's a lovely life. I'm whoever you want me to be.
Silver silverware - Where is the love? At least I can stay in character.
Oval swimming pool - Where is the love? Annoying Usenet one post at a time.
Damn the living - It's a lovely life. Blessed be.

Chïna Blüe Öyster Cult, Oct 1, 2010

3. ### August KarlstromGuest

On 2010-10-02 00:08, Chïna Blüe Öyster Cult wrote:
> In article<i85kc7\$mcj\$>,
> August Karlstrom<> wrote:
>
>> (x == 0)? x++: y *= 2;
>>

>
> Can you guarentee what will be assigned to what if x==0 or x==1? If not, you
>
> Also x++ is a rvalue, not an lvalue, so even if ?: has been extended to lvalues,
> this won't work.

OK, I apparently need parentheses around `y *= 2' so it should read

(x == 0)? x++: (y *= 2);

/August

--
The competent programmer is fully aware of the limited size of his own
skull. He therefore approaches his task with full humility, and avoids
clever tricks like the plague. --Edsger Dijkstra

August Karlstrom, Oct 2, 2010
4. ### August KarlstromGuest

On 2010-10-01 23:38, August Karlstrom wrote:
> (x == 0)? x++: y *= 2;

It should be

(x == 0)? x++: (y *= 2);

/August

--
The competent programmer is fully aware of the limited size of his own
skull. He therefore approaches his task with full humility, and avoids
clever tricks like the plague. --Edsger Dijkstra

August Karlstrom, Oct 2, 2010
5. ### Guest

August Karlstrom <> wrote:
>
> It should be
>
> (x == 0)? x++: (y *= 2);

No, it should be

if (x == 0) x++;
else y *= 2;

It is considered very poor style to use ?: and ignore the result -- an
if statment is clearer and avoids the precedence issues.
--
Larry Jones

, Oct 2, 2010
6. ### Mr. BuffoonGuest

Am 01.10.2010 23:38, schrieb August Karlstrom:
> Among C programmers it is not uncommon to use expressions
> with side-effects such as `y++' in the statement `x = y++;'.
> If we look at a statement like
> (x == 0)? x++: y *= 2;

Change to a compiler which automatically fixes your buggy code!

Mr. Buffoon, Oct 2, 2010
7. ### August KarlstromGuest

On 2010-10-02 02:21, wrote:
> August Karlstrom<> wrote:
>>
>> It should be
>>
>> (x == 0)? x++: (y *= 2);

>
> No, it should be
>
> if (x == 0) x++;
> else y *= 2;
>
> It is considered very poor style to use ?: and ignore the result -- an
> if statment is clearer and avoids the precedence issues.

OK, let's change it to

z = (x == 0)? x++: (y *= 2);

then.

Note that I would never write this kind of code myself. I wouldn't even
write `x = y++;' but `x = y; y++;'. What I'm trying to find out is
whether there is some common acceptance level among seasoned C
programmers of how convoluted the code is allowed to be.

/August

--
The competent programmer is fully aware of the limited size of his own
skull. He therefore approaches his task with full humility, and avoids
clever tricks like the plague. --Edsger Dijkstra

August Karlstrom, Oct 2, 2010
8. ### EdwardGuest

August Karlstrom wrote:
> Among C programmers it is not uncommon to use expressions with
> side-effects such as `y++' in the statement `x = y++;'. If we look at a
> statement like
>
> (x == 0)? x++: y *= 2;
>
>
>
> /August
>

It depends. If you're entering the IOCCC, it's acceptable if a little
have to work to understand the code, the more likely subtle bugs are to
get past you - as with the precedence problem in your above code that
other posters have identified.
-Edward
--
"Sanity" is the last refuge of the unimaginative.
visit my useless website -- http://dev-null.chu.cam.ac.uk

Edward, Oct 2, 2010
9. ### Kenny McCormackGuest

In article <i871og\$lnr\$>,
August Karlstrom <> wrote:
....
>Note that I would never write this kind of code myself. I wouldn't even
>write `x = y++;' but `x = y; y++;'. What I'm trying to find out is
>whether there is some common acceptance level among seasoned C
>programmers of how convoluted the code is allowed to be.

All you're going to get here is "Don't do that!"

--
"We should always be disposed to believe that which appears to us to be
white is really black, if the hierarchy of the church so decides."

- Saint Ignatius Loyola (1491-1556) Founder of the Jesuit Order -

Kenny McCormack, Oct 2, 2010
10. ### August KarlstromGuest

On 2010-10-02 14:28, Edward wrote:
> It depends. If you're entering the IOCCC, it's acceptable if a little
> too readable. Anywhere else, it's asking for trouble. The harder you
> have to work to understand the code, the more likely subtle bugs are to
> get past you

Exactly. As I have already mentioned in this thread I wouldn't write
this kind of code myself. Would you also reject the string copy idiom

while (*t++ = *s++);

with the same motivation?

/August

--
The competent programmer is fully aware of the limited size of his own
skull. He therefore approaches his task with full humility, and avoids
clever tricks like the plague. --Edsger Dijkstra

August Karlstrom, Oct 2, 2010
11. ### Ben BacarisseGuest

August Karlstrom <> writes:
<snip>
> OK, let's change it to
>
> z = (x == 0)? x++: (y *= 2);
>
> then.
>
> Note that I would never write this kind of code myself. I wouldn't
> even write `x = y++;' but `x = y; y++;'. What I'm trying to find out
> is whether there is some common acceptance level among seasoned C
> programmers of how convoluted the code is allowed to be.

One reason there have not been many answers could be that the answer
probably depends on the context and the exact details of the
expressions. I don't have a built-in aversion to side effects in the
arms of a conditional, but I am having trouble thinking of an example
where the rather wild pattern you quote is the best way to write
something specific.

The best I've been able to come up with is merging two arrays into one
where it might be reasonable (depending on the termination condition) to
write the core of the loop as:

m[i++] = a[j] < b[k] ? a[j++] : b[k++];

but here the side effects are not as bizarrely unrelated as x++ and y *=
2 and that symmetry makes it seem quite reasonable to me.

--
Ben.

Ben Bacarisse, Oct 2, 2010
12. ### EdwardGuest

August Karlstrom wrote:
> On 2010-10-02 14:28, Edward wrote:
>> It depends. If you're entering the IOCCC, it's acceptable if a little
>> too readable. Anywhere else, it's asking for trouble. The harder you
>> have to work to understand the code, the more likely subtle bugs are to
>> get past you

>
> Exactly. As I have already mentioned in this thread I wouldn't write
> this kind of code myself. Would you also reject the string copy idiom
>
> while (*t++ = *s++);
>
> with the same motivation?
>
>
> /August
>

No, I think that's reasonable (essentially it's describing an LDCPIR,
which one would hope the compiler would be clever enough to optimise it
into), except that if using the result of an assignment as a condition
you should enclose in an extra set of brackets. Typically your compiler
should warn you otherwise (as you might have meant == instead). Of
course, unless you want to compare to something other than zero,
string.h's strcpy() would be more appropriate.
The interesting one, though, is if you want to copy within an array,
perhaps even copying between regions which overlap - since then you need
to be able to choose whether it LDIRs or LDDRs. In that case you might
have something like
while(i++,a[i-1]=a);
to shift down, but
while(a=a[i-1],i--);
to shift up (of course you'd have to initialise i appropriately).
You have to be careful, though, not to invoke UB with something like
that (hence why I've used separate comma expressions to inc/dec i).
-Edward

--
"Sanity" is the last refuge of the unimaginative.
visit my useless website -- http://dev-null.chu.cam.ac.uk

Edward, Oct 2, 2010
13. ### Guest

August Karlstrom <> wrote:
>
> Note that I would never write this kind of code myself. I wouldn't even
> write `x = y++;' but `x = y; y++;'. What I'm trying to find out is
> whether there is some common acceptance level among seasoned C
> programmers of how convoluted the code is allowed to be.

It's allowed to be as convoluted as it needs to be, but no more.
--
Larry Jones

Bad news, Mom. I promised my soul to the Devil this afternoon. -- Calvin

, Oct 2, 2010
14. ### FredKGuest

"August Karlstrom" <> wrote in message
news:i871og\$lnr\$...
> On 2010-10-02 02:21, wrote:
>> August Karlstrom<> wrote:

>
> Note that I would never write this kind of code myself. I wouldn't even
> write `x = y++;' but `x = y; y++;'. What I'm trying to find out is whether
> there is some common acceptance level among seasoned C programmers of how
> convoluted the code is allowed to be.
>

Frankly, I almost never use ++ or -- unless I'm operating on a pointer. x
+= 1; is much clearer and generates the same code as x++; if what you really
are doing is incrementing by 1.

Saving a line of source generally doesn't make the generated code any
better/faster and can make the code less obvious.

FredK, Oct 2, 2010
15. ### August KarlstromGuest

On 2010-10-02 17:18, Richard wrote:
>> Note that I would never write this kind of code myself. I wouldn't even
>> write `x = y++;' but `x = y; y++;'. What I'm trying to find out is

>
> That is ridiculous.
>
> More statements.

But less subtlety and in my opinion a cleaner (de)composition of side
effects.

> If ANY C programmer doesnt understand "x=y++;" he has no right to be a C
> programmer.
>
> If I saw your way my first reaction would "uh oh, a total C amateur, I
> wonder what else is screwed up because he cant cope with the language
> constructs"?

C gives you the freedom to be non-terse as well.

>> whether there is some common acceptance level among seasoned C
>> programmers of how convoluted the code is allowed to be.
>>
>> /August

>
> x=y++ is not convoluted. It's a basic of C.
>
> These kind of shortcuts make it elegant.

Beauty is in the eye of the beholder.

/August

--
The competent programmer is fully aware of the limited size of his own
skull. He therefore approaches his task with full humility, and avoids
clever tricks like the plague. --Edsger Dijkstra

August Karlstrom, Oct 2, 2010
16. ### August KarlstromGuest

On 2010-10-02 20:19, FredK wrote:
> Frankly, I almost never use ++ or -- unless I'm operating on a pointer. x
> += 1; is much clearer and generates the same code as x++; if what you really
> are doing is incrementing by 1.

My point is not so much about the syntax. I'm fine with ++ but the
"problem" in my opinion is when its value is used.

> Saving a line of source generally doesn't make the generated code any
> better/faster and can make the code less obvious.

Agreed. To me being able to read the meaning of a statement aloud is a
necessary condition of clarity.

/August

--
The competent programmer is fully aware of the limited size of his own
skull. He therefore approaches his task with full humility, and avoids
clever tricks like the plague. --Edsger Dijkstra

August Karlstrom, Oct 2, 2010
17. ### Keith ThompsonGuest

"FredK" <> writes:
[...]
> Frankly, I almost never use ++ or -- unless I'm operating on
> a pointer. x += 1; is much clearer and generates the same code
> as x++; if what you really are doing is incrementing by 1.

Really? I find "x++" clearer than "x += 1"; if I see the latter,
I'm just going to wonder why the author didn't use "x++".

And why don't use "x += 1" for pointers?

> Saving a line of source generally doesn't make the generated code any
> better/faster and can make the code less obvious.

"x++" doesn't save a line of source. It's just clearer to most
experienced C programmers.

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson, Oct 2, 2010
18. ### August KarlstromGuest

On 2010-10-02 16:15, Edward wrote:
> August Karlstrom wrote:
>> Would you also reject the string copy idiom
>>
>> while (*t++ = *s++);
>>
>> with the same motivation?
>>

[...]
> if using the result of an assignment as a condition
> you should enclose in an extra set of brackets. Typically your compiler
> should warn you otherwise (as you might have meant == instead).

Why should we as C programmers allow ourselves to be dumbed down by the
compiler? We know what we're doing, right? (Just trying a different
standpoint.)

> Of course, unless you want to compare to something other than zero,
> string.h's strcpy() would be more appropriate.
> The interesting one, though, is if you want to copy within an array,
> perhaps even copying between regions which overlap - since then you need
> to be able to choose whether it LDIRs or LDDRs. In that case you might
> have something like
> while(i++,a[i-1]=a);
> to shift down, but
> while(a=a[i-1],i--);
> to shift up (of course you'd have to initialise i appropriately).
> You have to be careful, though, not to invoke UB with something like
> that (hence why I've used separate comma expressions to inc/dec i).

You're missing the point. The discussion is not about copying arrays.

/August

--
The competent programmer is fully aware of the limited size of his own
skull. He therefore approaches his task with full humility, and avoids
clever tricks like the plague. --Edsger Dijkstra

August Karlstrom, Oct 2, 2010
19. ### EdwardGuest

August Karlstrom wrote:
> On 2010-10-02 16:15, Edward wrote:
>> August Karlstrom wrote:
>>> Would you also reject the string copy idiom
>>>
>>> while (*t++ = *s++);
>>>
>>> with the same motivation?
>>>

> [...]
>> if using the result of an assignment as a condition
>> you should enclose in an extra set of brackets. Typically your compiler
>> should warn you otherwise (as you might have meant == instead).

>
> Why should we as C programmers allow ourselves to be dumbed down by the
> compiler? We know what we're doing, right? (Just trying a different
> standpoint.)

.... because useful warnings that prevent common mistakes are a Good Thing?

>> Of course, unless you want to compare to something other than zero,
>> string.h's strcpy() would be more appropriate.
>> The interesting one, though, is if you want to copy within an array,
>> perhaps even copying between regions which overlap - since then you need
>> to be able to choose whether it LDIRs or LDDRs. In that case you might
>> have something like
>> while(i++,a[i-1]=a);
>> to shift down, but
>> while(a=a[i-1],i--);
>> to shift up (of course you'd have to initialise i appropriately).
>> You have to be careful, though, not to invoke UB with something like
>> that (hence why I've used separate comma expressions to inc/dec i).

>
> You're missing the point. The discussion is not about copying arrays.
>
>
> /August

Except that the code snippet you gave was copying strings, and strings
behave very similarly to arrays of char under many circumstances. Of
course, I could have contrasted "t=s+1; while(s++=t++);" with "t=s+1;
while(t--=s--);", but typically the latter would be problematic as
strings, though they end with (char)0, tend not to begin with it.
Hence, moving a string in-place to one character forward (eg. with the
intention of inserting a new character in front of it) is more likely to
be performed by treating the string as an array of char and using the
index, rather than the copied value, in the loop condition.

I should also note that the code I posted before has an off-by-one bug;
instead of i-- it should use --i.

-Edward

--
"Sanity" is the last refuge of the unimaginative.
visit my useless website -- http://dev-null.chu.cam.ac.uk

Edward, Oct 2, 2010
20. ### James Dow AllenGuest

On Oct 3, 2:47 am, Richard <> wrote:
> Keith Thompson <> writes:
> > "FredK" <> writes:
> >> Frankly, I almost never use ++ or -- unless I'm operating on
> >> a pointer.  x += 1; is much clearer and generates the same code
> >> as x++; if what you really are doing is incrementing by 1.

I don't avoid ++ on non-pointers: often the brevity seems
just right, especially in a common idiom like
for ( ; Foo; index++)
yet nevertheless I frequently write
baz += 1
especially when the fact the addend happens to be 1 exactly
seems incidental.

> > Really?  I find "x++" clearer than "x += 1"; if I see the latter,
> > I'm just going to wonder why the author didn't use "x++".

Wondering whether the coder knows ++x and x+=1 are the same????
Wondering is good, but you might be overdoing it.

> If the author is too dumb to understand x++ then one has to wonder what
> else they dont understand.

So if you happened on an x += 1 in my code, you'll assume
I don't understand C??

> "Avoid hyperbole at all costs, its the most destructive argument on
> the planet" - Mark McIntyre in comp.lang.c

You seem to find the 2nd clause in your .sig amusing.
Perhaps you should seek wisdom in the 1st clause.

James Dow Allen

James Dow Allen, Oct 2, 2010