strange feature... or bug

S

sonic

Please tell me what is wrong (and for me to avoid browsing through
200k something messages
) or am i missing something obvious (btw i've tested with gcc on
latest Tiger OS X and linux); or should i post to gcc?

---------------------------
#include <stdio.h>

int main()
{
int i = 2;
i = (i*=1 ? i-2 : 0);
printf("val is %d\n", i);
return 0;
}
--------------------------

you would expect to print 0 right, it does!

removed -2, like:

-------------------------
#include <stdio.h>

int main()
{
int i = 2;
i = (i*=1 ? i : 0);
printf("val is %d\n", i);
return 0;
}
 
K

Keith Thompson

sonic said:
Please tell me what is wrong (and for me to avoid browsing through
200k something messages
) or am i missing something obvious (btw i've tested with gcc on
latest Tiger OS X and linux); or should i post to gcc?
[snip]

-------------------------
#include <stdio.h>

int main()
{
int i = 2;
i = (i*=1 ? i : 0);
printf("val is %d\n", i);
return 0;
}

I'll just address your second example.

In both programs, you modify 'i' twice between sequence points,
invoking undefined behavior.

Also, the spacing in your expression is inconsistent with the actual
operator precedence. The '?:' operator binds more tightly than an
assignment operator. Your statement
i = (i*=1 ? i : 0);
is equivalent to
i = (i *= (1 ? i : 0));
The subexpression '(1 ? i : 0)' can be reduced to 'i', giving:
i = (i *= i);
which still invokes UB.

If you start by thinking about what you want to do, and then write C
code to express your intent, you'll never write anything like that in
the first place.
 
R

Robert Gamble

Please tell me what is wrong (and for me to avoid browsing through
200k something messages
) or am i missing something obvious (btw i've tested with gcc on
latest Tiger OS X and linux); or should i post to gcc?

---------------------------
#include <stdio.h>

int main()
{
int i = 2;
i = (i*=1 ? i-2 : 0);
printf("val is %d\n", i);
return 0;}

--------------------------

you would expect to print 0 right, it does!

removed -2, like:

-------------------------
#include <stdio.h>

int main()
{
int i = 2;
i = (i*=1 ? i : 0);
printf("val is %d\n", i);
return 0;}

Both examples contain undefined behavior because i is assigned to
multiple times without an intervening sequence point. The problem is
that this may not be readily apparent in your example because of the
precedences of the of the *= and conditional operators. This line:

i = (i*=1 ? i : 0);

is equivalent to this one:

i = (i*= (1 ? i : 0));

which is equivalent to this:

i = i* = (1 ? i : 0);

Since this is undefined behavior anything is allowed although it
should be easy to see why the subexpression (which doesn't contain
UB):

i* = (1 ? i : 0);

would yield 4.

Robert Gamble
 
S

sonic

Many thanks for both of your answers Keith and Rob



In both programs, you modify 'i' twice between sequence points,
invoking undefined behavior. oops


operator precedence. The '?:' operator binds more tightly than an
assignment operator. Your statement

Many thanks! i understand it now!
i = (i *= i);
If you start by thinking about what you want to do, and then write C
code to express your intent, you'll never write anything like that in
the first place.
Actually i was just studying Confuscated C code and tried to exercie
mine a little bit and missed an obvious case with the precedence!
 
A

Ark Khasin

Keith Thompson wrote:
In both programs, you modify 'i' twice between sequence points,
invoking undefined behavior.

Also, the spacing in your expression is inconsistent with the actual
operator precedence. The '?:' operator binds more tightly than an
assignment operator. Your statement
i = (i*=1 ? i : 0);
is equivalent to
i = (i *= (1 ? i : 0));
The subexpression '(1 ? i : 0)' can be reduced to 'i', giving:
i = (i *= i);
which still invokes UB.
<snip>

Just wondering:
i = (i<2007)?(i+=0):(i*=1);
Is it still UB?
Or must an expression evaluate to one of the finite set of values
determined by the freedom of compiler's choice in the order of evaluation?
-- Ark
 
K

Keith Thompson

Ark Khasin said:
Keith Thompson wrote:

<snip>

Just wondering:
i = (i<2007)?(i+=0):(i*=1);
Is it still UB?
Or must an expression evaluate to one of the finite set of values
determined by the freedom of compiler's choice in the order of
evaluation?

That case (and the others) is slightly complicated by the fact that
there's a sequence point after the evaluation of the first operand of
a conditional operator. Nevertheless, I'm reasonably sure the
behavior is undefined.
 
F

Flash Gordon

Keith Thompson wrote, On 29/08/07 05:35:
That case (and the others) is slightly complicated by the fact that
there's a sequence point after the evaluation of the first operand of
a conditional operator. Nevertheless, I'm reasonably sure the
behavior is undefined.

Unless there is a sequence point after the evaluation of the second or
third argument then it is definitely UB. I believe there is no such
sequence point, so like you I am reasonably sure it is UB.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top