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.
Related
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).
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 1 year ago.
Why i can't do the following in Objective-C?
a = (a < 10) ? (a++) : a;
or
a = (a++)
The ++ in a++ is a post-increment. In short, a = a++ does the following:
int tmp = a; // get the value of a
a = a + 1 //post-increment a
a = tmp // do the assignment
As noted by others, in C this is actually undefined behavior and different compilers can order the operations differently.
Try to avoid using ++ and -- operators when you can. The operators introduce side effects which are hard to read. Why not simply write:
if (a < 10) {
a += 1;
}
To extend Sulthan's answer, there are several problem with your expressions, at least the simple assignment (case 2).
A. There is no sense in doing so. Even a++ has a value (is a non-void expression) that can be assigned, it automatically assigns the result to a itself. So the best you can expect is equivalent to
a++;
The assignment cannot improve the assignment at all. But this is not the error message.
B. Sulthans replacement of the statement is a better case. It is even worse: The ++ operator has the value of a (at the beginning of the expression) and the effect to increment a at some point in future: The increment can be delayed up to the next sequence point.
The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point.
(ISO/IEC 9899:TC3, 6.5.2.4, 2)
But the assignment operator = is not a sequence point (Annex C).
The following are the sequence points described in 5.1.2.3:
[Neither assignment operator nor ) is included in the list]
Therefore the expression can be replaced with what Sulthan said:
int tmp = a; // get the value of a
a = a + 1 //post-increment a
a = tmp // do the assignment
with the result, that a still contains the old value.
Or the expression can be replaced with this code …:
int tmp = a; // get the value of a
a = tmp // assignemnt
a = a + 1 // increment
… with a different result (a is incremented). This is what the error message says: There is no defined sequence (order the operations has to be applied.)
You can insert a sequence point using the comma operator , (what is the primary use of it), …
a++, a=a; // first increment, then assign
… but this shows the whole leak of meaning of what you want to do.
It is the same with your first example. Though ? is a sequence point …:
The following are the sequence points described in 5.1.2.3:
… The end of the first operand of the following operators: […] conditional ? (6.5.15);[…].
… both the increment (a++) and the assignment (a=) are after the ? operator is evaluated and therefore unsequenced ("in random order") again.
To make the comment "Be careful" more concrete: Don't use an incremented object in an expression twice. (Unless there is a clear sequence point).
int a = 1;
… = a++ * a;
… evaluates to what? 2? 1? Undefined, because the increment can take place after reading a "the second time".
BTW: The Q is not related to Objective-C, but to pure C. There is no Objective-C influence to C in that point. I changed the tagging.
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.)
main(){
int x = 256, y = 4;
printf("%d\n\n", x++ + ++y); //output = 261
printf("%d\n\n", x); // output = 257
printf("%d", y); // output = 5
}
Is the final answer 261, because 256 -> 257 (post operator) and 5 -> 5 (pre operator) cause 256 + 5 = 261?
Given:
int x = 256, y = 4;
printf("%d\n\n", x++ + ++y);
In short: The x++ returns the value 256 and then increments x to 257. The ++y increments y to 5 and returns the value 5. The addition, therefore, adds 256 and 5 yielding 261.
Long windedly: The x++ evaluates to the current value of x which is 256 and schedules an increment of x to 257. Similarly ++y schedules the increment of y to 5 and evaluates to the incremented value 5. The addition, therefore, adds 256 and 5 yielding 261. The order in which the terms involving x and y are evaluated is not defined, but both have to be evaluated before the addition (though the increments may not be complete when the addition is evaluated). Because there is a 'sequence point' when the arguments (and the expression denoting the function) have been evaluated but before the function is called, the increments must be complete when printf() is called.
The next two statements print x and y as 257 and 5.
Note that those two printf() operations could be combined into one. Neither could be combined with the first without invoking undefined behaviour. (See Multiple increments and undefined behaviour for more information on this topic.)
So, allowing for the fact that I would not express it quite the way you wrote it, you seem to have the correct explanation.
Also, Standard C has required a return type on all functions for over 15 years now (since C99 was standardized). You should write:
int main(void)
for a main() function that takes no arguments. (See What should main() return in C and C++? for the full details.)
Note that this question only invokes fully defined behaviour (at least, in the printf() statements). It is not asking about multiple increments on a single variable between sequence points.
It will show UNSPECIFIED behavior
In your case, we can't tell whether x++ will be evaluated first or ++y will be evaluated first. It is compiler dependent.
So don't use expressions involving a combination of post-increment or pre-increment operators in C or C++.
For more information refer to the link:
https://www.quora.com/What-does-an-expression-involving-multiple-post-pre-decrement-increment-operators-evaluate-to-in-C-and-C++#
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