Undefined Behavior. ..

C

coolguyaroundyou

Will the following statement invoke undefined behavior :

a^=b,b^=a,a^=b ;

given that a and b are of int-type ??

Be cautious, I have not written a^=b^=a^=b ; which, of course, is
undefined. I am having some confusion with the former statement!

Also, state the reason for the statement being undefined!
 
J

Joachim Schmitz

Will the following statement invoke undefined behavior :

a^=b,b^=a,a^=b ;

given that a and b are of int-type ??

No, because the comma operator constitutes a sequence point
Be cautious, I have not written a^=b^=a^=b ; which, of course, is
undefined. I am having some confusion with the former statement!

Also, state the reason for the statement being undefined!

6.5.17.1
The left operand of a comma operator is evaluated as a void expression;
there is a sequence point after its evaluation.

Bye, Jojo
 
C

c.lang.myself

<<Be cautious, I have not written a^=b^=a^=b ; which, of course, is
undefined. I am having some confusion with the former statement!>>

I think this expression is valid as assignment operator is evaluated
from right to left so it is parsed as
(a^=(b^=(a^=b)))
above expression swaps two numbers
please correct me if i am wrong...
 
J

Joachim Schmitz

<<Be cautious, I have not written a^=b^=a^=b ; which, of course, is
undefined. I am having some confusion with the former statement!>>

I think this expression is valid as assignment operator is evaluated
from right to left so it is parsed as
(a^=(b^=(a^=b)))
above expression swaps two numbers
please correct me if i am wrong...

This is modifying 'a' twice without an intermediate sequence point ->
undefined behavoir

Bye, Jojo
 
M

maverik

<<Be cautious, I have not written a^=b^=a^=b ; which, of course, is
undefined. I am having some confusion with the former statement!>>

I think this expression is valid as assignment operator is evaluated
from right to left so it is parsed as
(a^=(b^=(a^=b)))

6.5.17

1.
expression:
assignment-expression
expression , assignment-expression

2.
The left operand of a comma operator is evaluated as a void
expression; there is a sequence point after its evaluation. Then the
right operand is evaluated; the result has its type and value.

So, you have:

a^=b, b^=a, a^=b
[expression][assignment-expression]
|
a^=b, b^=a
[expression][assignment-expression]
|
a^=b
[assignment-expression]

OTOH, a^=b, b^=a, a^=b
[left operand] [right operand]

Left operand evaluted as void, and comma epression has a type and
value of right operand: a^=b.
But left operand if: a^=b, b^=a
And again: a^=b, b^=a
[left operand] [right operand]
Left operand evaluted as void, and comma epression has a type and
value of right operand: b^=a.

So, the sequnce should be like:
evalute a^=b, then b^=a, then a^=b.
You should get the same result as in this case:

a^=b;
b^=a;
a^=b;
 
J

James Kuyper

Will the following statement invoke undefined behavior :

a^=b,b^=a,a^=b ;

given that a and b are of int-type ??

That's perfectly safe. As a stand-alone statement, it is exactly
equivalent to

a^=b;
b^=a;
a^=b;

The use of the comma operator is only needed in cases like if(A; B; C),
where A, B, and C can only be a single statement. In any other context,
I'd recommend breaking it out into three separate statements, but only
for the sake of clarity - it's perfectly legal as a single statement.
Be cautious, I have not written a^=b^=a^=b ; which, of course, is
undefined. I am having some confusion with the former statement!

Also, state the reason for the statement being undefined!

6.5p2: "Between the previous and next sequence point an object shall
have its stored value modified at most once by the evaluation of an
expression".

Because the second version violates a "shall" occurring outside of a
"Constraints" section, the behavior is undefined.

The key difference between the two statements is the presence of the ','
operators in the first version. The ',' operator inserts a sequence
point separating it's two operands.
 
C

c.lang.myself

This is modifying 'a' twice without an intermediate sequence point ->
undefined behavoir

Bye, Jojo

sorry,I am still not able to get it...

now again consider a^=b^=a^=b
when compiler see this expression it starts from RHS as assignment
operator is right associative
so first it has to calculate rightmost a^=b then value of a must have
to change....it porceedes then to calculate b^=a ..then again a^=b....

as we can also use a=b=3;
Do you mean that after right most a^=b,we can not be sure that value
of a is changed till we get sequence point...
but a=b=3 is valid

Please clear my confusion...
thanks,
 
V

vippstar

sorry,I am still not able to get it...

What don't you get?
now again consider a^=b^=a^=b
when compiler see this expression it starts from RHS as assignment

Wrong, when the compiler sees that expression, he can do whatever he
wants because that expression invokes undefined behavior.
operator is right associative

Uh, no, it's UB.
so first it has to calculate rightmost a^=b then value of a must have

Uh, no, it's UB.
to change....it porceedes then to calculate b^=a ..then again a^=b....

Uh, no, it's UB.
as we can also use a=b=3;

That's different than the former expression, because in that
expression a and b are modified only once between sequence points.
Do you mean that after right most a^=b,we can not be sure that value

No, a^=b^=a^=b invokes UB and if you have that in your code, you can't
be sure of anything at all.
but a=b=3 is valid
Please clear my confusion...

For the reasons I explained before. Now I have a question: How the
hell do you know that a = b = 3 is valid if you don't understand and
you're confused?
 
H

Harald van Dijk

Wrong, when the compiler sees that expression, he can do whatever he
wants because that expression invokes undefined behavior.

When the compiler sees that expression, it cannot be sure whether it will
be executed. It must compile the code, and if the program reaches the
point where the expression is evaluated, _then_ the behaviour is
undefined. The compiler cannot do whatever it wants. The compiler can make
the resulting code do whatever it wants.
Uh, no, it's UB.

Uh, yes, ^= is right associative. The behaviour is undefined but that does
not affect parsing.
 
V

vippstar

When the compiler sees that expression, it cannot be sure whether it will
be executed. It must compile the code, and if the program reaches the
point where the expression is evaluated, _then_ the behaviour is
undefined. The compiler cannot do whatever it wants. The compiler can make
the resulting code do whatever it wants.

What ELSE could the compiler do other than having the output be
whatever he wants? I don't think you've really added to what I said.
Uh, yes, ^= is right associative. The behaviour is undefined but that does
not affect parsing.

Well, UB is when the standard doesn't impose any requirements for the
behavior of the implementation. You'd argue that 'parsing' is not
included in 'behavior'? You might be right but I'd like quotes from
the standard to trust you. (you are certainly credible, but c&v from
the standard is always nice)
 
J

James Kuyper

Harald said:
When the compiler sees that expression, it cannot be sure whether it will
be executed. It must compile the code, and if the program reaches the
point where the expression is evaluated, _then_ the behaviour is
undefined. The compiler cannot do whatever it wants. The compiler can make
the resulting code do whatever it wants.

The standard quite explicitly says that the consequences of undefined
behavior can include failing to compile, which clearly indicates that it
can precede execution of the relevant code. The standard does not
explain this in any detail, but I believe that the relevant rule is that
the undefined behavior is allowed at any point after execution of the
relevant code becomes inevitable.

Example:

if(some condition)
a^=b^=a^=b;

For code like this, the behavior of the code becomes undefined as soon
as it becomes inevitable that the if() clause will be executed. This
means that at points in the code prior the if() statement, the compiler
is allowed to generate code using optimizations that only work if the
if-condition is not true. As a result, those optimizations may cause
your code to misbehave long before evaluation of the offending statement.
 
H

Harald van Dijk

The standard quite explicitly says that the consequences of undefined
behavior can include failing to compile,

It does quite explicitly say so, but there is a distinction between
compile-time undefined behaviour and run-time undefined behaviour (not
spelled out in the standard, but made explicit in DRs). This is run-time
undefined behaviour, where refusing to compile is permitted only if the
compiler can prove that the code would always be executed.
which clearly indicates that it
can precede execution of the relevant code. The standard does not
explain this in any detail, but I believe that the relevant rule is that
the undefined behavior is allowed at any point after execution of the
relevant code becomes inevitable.

I agree with this.
 
H

Harald van Dijk

On Nov 15, 2:39 pm, "c.lang.mys[298][email protected]"
now again consider a^=b^=a^=b
when compiler see this expression it starts from RHS as assignment
Wrong, when the compiler sees that expression, he can do whatever he
wants because that expression invokes undefined behavior.

When the compiler sees that expression, it cannot be sure whether it
will be executed. It must compile the code, and if the program reaches
the point where the expression is evaluated, _then_ the behaviour is
undefined. The compiler cannot do whatever it wants. The compiler can
make the resulting code do whatever it wants.

What ELSE could the compiler do other than having the output be whatever
he wants? I don't think you've really added to what I said.

A non-conforming compiler could give an error message and refuse to
compile any program containing a^=b^=a^=b, but a conforming compiler is
not allowed to do so (or at least not always).
Well, UB is when the standard doesn't impose any requirements for the
behavior of the implementation.

Yes, but to get to the part where the standard says the behaviour is
undefined you need to have already parsed the expression. I can't give an
exact chapter and verse, but can you explain how you can determine that
the behaviour is undefined without parsing?
 
V

vippstar

39 pm, "c.lang.mys[298].[390][email protected]"
now again consider a^=b^=a^=b
when compiler see this expression it starts from RHS as assignment
Wrong, when the compiler sees that expression, he can do whatever he
wants because that expression invokes undefined behavior.
When the compiler sees that expression, it cannot be sure whether it
will be executed. It must compile the code, and if the program reaches
the point where the expression is evaluated, _then_ the behaviour is
undefined. The compiler cannot do whatever it wants. The compiler can
make the resulting code do whatever it wants.
What ELSE could the compiler do other than having the output be whatever
he wants? I don't think you've really added to what I said.

A non-conforming compiler could give an error message and refuse to
compile any program containing a^=b^=a^=b, but a conforming compiler is
not allowed to do so (or at least not always).

Wrong, a conforming compiler can reject that code. The reason might be
quite different than the expression, but it serves more like an excuse
to reject this. For example, the compiler could claim (assuming a, b,
int) that the source exceeds the environmental limits.
Yes, but to get to the part where the standard says the behaviour is
undefined you need to have already parsed the expression. I can't give an
exact chapter and verse, but can you explain how you can determine that
the behaviour is undefined without parsing?

If I understand, what you're saying is that the semantics of something
are not affected by UB, well that's wrong I believe. ^= doesn't need
to be anything meaningful after the first UB in source code.
 
H

Harald van Dijk

Wrong, a conforming compiler can reject that code. The reason might be
quite different than the expression, but it serves more like an excuse
to reject this. For example, the compiler could claim (assuming a, b,
int) that the source exceeds the environmental limits.

Heh, that's nasty. I suppose it has to also reject a^=b^=c^=d, then, to
cover up its lie? I can't think of a limit right now that a^=b^=a^=b might
exceed that a^=b^=c^=d doesn't, and if you can, then I can try to come up
with another valid example that also exceeds that limit. :)
If I understand, what you're saying is that the semantics of something
are not affected by UB, well that's wrong I believe.

Yes, that is wrong, and no, that is not what I'm saying.
^= doesn't need to
be anything meaningful after the first UB in source code.

To determine that a^=b^=a^=b modifies a at all, you need to already have
determined that this is an assignment-expression with only a as its left
operand. In other words, that it is equivalent to a^=(b^=(a^=b)) instead
of ((a^=b)^=a)^=b. The latter is simply a constraint violation and
attempts to modify a only once: the other ^= operators attempts to modify
the result of an assignment.
 
V

vippstar

Heh, that's nasty. I suppose it has to also reject a^=b^=c^=d, then, to
cover up its lie? I can't think of a limit right now that a^=b^=a^=b might
exceed that a^=b^=c^=d doesn't, and if you can, then I can try to come up
with another valid example that also exceeds that limit. :)

There's no need for that, a conforming compiler can also reject
a^=b^=c^=d for the same reason.
Also, a compiler doesn't have to cover up its lies as there's no such
requirement. My point is that a conforming compiler can reject
anything, and a compiler can output anything when UB is encountered. I
believe that to be true, and I think the requirements the standard
sets on an implemenations agree with those words.
Yes, that is wrong, and no, that is not what I'm saying.

Alright then...
To determine that a^=b^=a^=b modifies a at all, you need to already have
determined that this is an assignment-expression with only a as its left
operand. In other words, that it is equivalent to a^=(b^=(a^=b)) instead
of ((a^=b)^=a)^=b. The latter is simply a constraint violation and
attempts to modify a only once: the other ^= operators attempts to modify
the result of an assignment.

Hmm... then yes, I was wrong on the original matter.
 
C

c.lang.myself

For the reasons I explained before. Now I have a question: How the
hell do you know that a = b = 3 is valid if you don't understand and
you're confused

Now i am able to get it.
I know a=b=3 is valid as i read it in my C text book but i had not
read other undefined statement in this thread so i was confused about
it...
 
V

vippstar

I know a=b=3 is valid as i read it in my C text book but i had not
read other undefined statement in this thread so i was confused about
it..

Which book and page?
 

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,982
Messages
2,570,186
Members
46,742
Latest member
AshliMayer

Latest Threads

Top