Increment and decrement operators in one statement in C [duplicate] - c

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 3 years ago.
I know it is theoretically undefined behavior and of course bad style. This is the example of a school (I am not the pupil).
But why do I get 7 (example a) resp. 1 (example b) out of this operation:
Online example:
https://onlinegdb.com/B172lj8k8
a:
#include <stdio.h>
int main()
{
int i = 2;
printf("%d; i=%d", ++i + i++, i);
return 0;
}
b:
#include <stdio.h>
int main()
{
int i = 2;
printf("%d; i=%d", ++i - i++, i);
return 0;
}
In my opinion the output should be 6 and 2.
Execute i++, yield 2, increment i
Execute ++i yield 4
Additon 2 + 4
The other example should be 4 - 2.
Exexcuting the increment in a statement seems to yield the result of the increment immediately, no matter if it is postfix or prefix, which is odd. Or do I get it wrong totally?

The order in which the arguments passed to a function are evaluated is not specified, and the order of evaluating the operants of + is unspecified, too.
So in printf("%d %d", i+1, i-1), for example, you cannot rely on the order of evaluation of the arguments; i+1 might be evaluated after i-1, actually; You will not recognise, since the evaluation of the one does not effect the result of the other.
In conjunction with "side effects" like the post-increment i++, however, the effect of incrementing i at a specific point in time might influence the result of other evaluations based on i. Therefore, it is "undefined behaviour" in C, if a variable is used more than once in an expression and a side effect changes its value (formally, to be precise, if there is no sequence point in between).

Related

Understanding Post increment concept in C [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Sequence Points between printf function args; does the sequence point between conversions matter?
(3 answers)
Closed 3 years ago.
Consider code below:
#include <stdio.h>
int main()
{
int x=0,y=5;
printf("x=%d,x_1=%d,sum=%d",x++,x,y+x);
return 0;
}
My assumption on this code was that, x would be printed as 0 and later on postincrement x_1 would be 1 and y+x be 5+1=6
Actual result is x as 0 as expected , x_1 as 1 as expected. But y+x be 5. I am unsure why x retains its previous value though an postincrement had occured. Could you please help clarify this?
I used gcc compiler for the same.
In
printf("x=%d,x_1=%d,sum=%d", x++, x, y+x);
// (a) (b) (b)
you are both updating x (a) and using its value (b) in the same expression (with no intervening sequence point).
That's Undefined Behaviour.
Try
printf("x=%d,x_1=%d,sum=%d", x, x + 1, y + x + 1);
x++;
This is standard undefined behaviour, order of evalution of function arguments is non deterministic. Read [Why are these constructs using pre and post-increment undefined behavior?

C, pre and post increment, different answers in different programs [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 6 years ago.
testing some code when studying C language,
#include <stdio.h>
#include <math.h>
#define hypotenusa(x, y) sqrt((x) * (x) + (y) * (y))
int main(void) {
int a, x;
x = 2;
a = hypotenusa(++x, ++x);
printf("%d\n", a);
}
And I am getting the answer
6 in one program(dosbox gcc compiler)
7 in codelight gcc compiler and
8 on codeChef online compiler
can anyone explain this behaviour?
my logic says it should be 6 (sqrt(42)) but...
It's undefined behaviour.
After the macro replacement
a = hypotenusa(++x, ++x);
becomes:
a = sqrt((++x) * (++x) + (++x) * (++x));
As you can see x is modified multiple times without any intervening sequence point(s). See What Every C Programmer Should Know About Undefined Behavior.
hypotenusa(++x, ++x) is undefined behavior.
It is up to the compiler which of the parameters gets incremented (and pushed) first - after the macro expansion, there are a total of four instances, and the sequence is not defined.
You should never increment the same variable multiple times in the same statement, to avoid this kind of issues. Using a variable twice in a macro can hide this error and make it really nasty.
The behavior of your macro is undefined, meaning any result is possible.
Chapter and verse
6.5 Expressions
...
2 If a side effect on a scalar object is unsequenced relative to either a different side effect
on the same scalar object or a value computation using the value of the same scalar
object,
the behavior is undefined. If there are multiple allowable orderings of the
subexpressions
of an expression, the behavior is undefined if such an unsequenced side
effect occurs in any
of the orderings.84)
84) This paragraph renders undefined statement expressions such as i = ++i + 1;
a[i++] = i;
while allowing i = i + 1;
a[i] = i;
Basically, if you modify the value of an object more than once in an expression, or both modify an object and use its value in a computation in an expression, the result will not be well-defined unless there is a sequence point in between those operations. With a few exceptions, C does not force left-to-right evaluation of expressions or function parameter evaluations, nor does it mandate that the side effect of ++ or -- be applied immediately after evaluation. Thus, the result of an expression like x++ * x++ will vary from platform to platform, program to program, or even potentially from run to run (although I've never seen that in practice).
For example, given the expression y = x++ * x++, the following evaluation sequence is possible:
t0 <- x // right hand x++, t0 == 2
t1 <- x // left hand x++, t1 == 2
y <- t0 * t1 // y = 2 * 2 == 4
x <- x + 1 // x == 3
x <- x + 1 // x == 4
which doesn't give you the result you expect if you assume left-to-right evaluation.

Evaluation of Expressions inside printf in C [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 6 years ago.
I know that multiple expressions are evaluated from right to left.
Ex:
int i = 0;
printf("%d %d %d", i, i++, i++); // Prints 2 1 0
But when it comes to each expression to be evaluated, i'm not getting if it is from right to left or vice versa.
int main()
{
int a = 1, b = 1, d = 1;
printf("%d", a + ++a); // Result = 4
}
Considering evaluation from left to right, the preceding code should be evaluated as 1 + 2 = 3
int main()
{
int a = 1, b = 1, d = 1;
printf("%d", ++a + a); // Result = 4
}
And this should Evaluate as 2 + 2 = 4
But in both the cases the answer is 4.
Can anyone explain how these expressions are evaluated?
I know that multiple expressions are evaluated from right to left.
No. The order of evaluation of function parameters is unspecified behavior. Meaning you can't know the order, it may differ from system to system or even from function call to function call. You should never write programs that rely on this order of evaluation.
In addition, there is no sequence point between the evaluation of function parameters, so code like printf("%d", ++a + a); also invokes undefined behavior, see Why are these constructs (using ++) undefined behavior?.
Please note that operator precedence and operator associativity only guarantees the order in which an expression is parsed! This is not related to the order of evaluation of the operands. (With a few special exceptions such as || && , ?: operators.)

C side effects in gcc (prefix/postfix operator and precedence) [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 5 years ago.
i have small C code:
#include<stdio.h>
int main()
{
int z[]= {1,2,3,4,5,6};
int i = 2, j;
printf("i=%d \n",i);
z[i] = i++;
for (j=0;j < 6;j++ )
printf ("%d ", z[j]);
printf("\ni=%d \n",i);
}
output:
i=2
1 2 2 4 5 6
i=3
The order of precedence to evaluate the expression is
First, z[i] is evaluated. As i is 2 here, it becomes z[2].
Next, i++ is evaluated i.e 2 is yielded and i becomes 3.
Finally, = is executed, and 2 (i.e value yielded from i++) is put to z[2]
This explains the above output i.e 1 2 2 4 5 6
But if we change the above code from i++ to ++i i.e
#include<stdio.h>
int main()
{
int z[]= {1,2,3,4,5,6};
int i = 2, j;
printf("i=%d \n",i);
z[i] = ++i;
for (j=0;j < 6;j++ )
printf ("%d ", z[j]);
printf("\ni=%d \n",i);
}
Then the Output is strangely different, which is:
i=2
1 2 3 3 5 6
i=3
if we go by the above precedence (what C spec says [index] are bound earlier than ++) then
the output should have been 1 2 3 4 5 6.
I just wish to know that why the above order of precedence does not explains this ?
my compiler is gcc 4.5.2 on ubuntu 11.04
Thanks and Regards,
Kapil
z[i] = ++i; results in undefined behavior:
6.5 Expressions
...
2 If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar
object, the behavior is undefined. If there are multiple allowable orderings of the
subexpressions of an expression, the behavior is undefined if such an unsequenced side
effect occurs in any of the orderings.84)
84) This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
Note that precedence only controls the grouping of operators and operands; it does not control the order of evaluation.
The side effect of the ++ operator in ++i is unsequenced relative to the [] operator in z[i]; the compiler is not required to evaluate the two expressions in any particular order. Also note that the side effect of ++i need not be applied immediately after the expression is evaluated; it only needs to be applied before the next sequence point.
This is not a bug, take a look at the GCC non-bug section. This kind of tests will cause unpredictable results and they know it.
Modifying a value twice between two sequence points [...] leads to undefined behavior.
z[i] = ++i;
is undefined behaviour
To quote from C section of cppreference.com
1) If a side effect on a scalar object is unsequenced relative to
another side effect on the same scalar object, the behavior is
undefined.
i = ++i + i++; // undefined behavior
z[i] = ++i;
invokes undefined behaviour.
See http://www.faqs.org/faqs/C-faq/faq/ Questions 3.1 to 3.9. These are pretty much answers to all questions similar to your question.
But in short, order of evaluation between two sequence points (these are well-defined by C standard - C99 Annex C) is undefined behavior.
Between two sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored

Undefined behavior while using increment operator [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 3 years ago.
I am new to C, i have an Increment operator program in C
#include<stdio.h>
main(){
int a, b;
a = 2;
b = a + ++a + ++a;
printf("%d", b);
getchar();
}
The output is 10, can someone explain me how the output will be 10 .
a + ++a + ++a;
Behaviour for this is undefined.
The compiler might generated code that evaluated this as 2 + 4 + 4 or 3 + 3 + 4, but any combination/ordering of incrementing and accessing is a "valid" result.
This is undefined, the ++i can happen in any order.
Function call arguments are also ambigiously evaluated, e.g. foo(++i,++i).
Not all operator chains are undefined, a||b||c is guaranteed to be left-to-right, for example.
The guarantees are made in places known as sequence points although this terminology is being deprecated and clarified in C++0x.
What's odd in your example is that neigher 2+3+4 nor 4+4+3 happened, so the compiler evaluated the left side first in one step and the right side first in the other. This was probably an optimisation to flatten the depencency graph.

Resources