C++ Code displays different, which is unexpected, output in different compilers - c++

This is a beginners question.
Following is the C++ code that I was working with
int main() {
int x=5, y=5;
cout<<x--;
cout<<",";
cout<<--x;
cout<<",";
cout<<y--<<","<<--y;
return 0;
}
When run in Turbo C++ 3.0 the following is the output displayed by the code:
5,3,4,4
When compiled with Code::Blocks on Windows (uses MinGW with GCC/G++) the following is the output displayed:
5,3,4,3
Previously, I have heard that sometimes different compilers behave differently to certain problems, but I don't understand why this result is being displayed. Since logically, as I think, the output should be:
5,3,5,3
Can you please tell me the reason for such output logically.
Thank you!

There is no right or wrong output. Your code has undefined behavior and anything is possible.
The reason lies in paragraph 1.9.15 (n3337) of C++ standard (emphasis mine):
Except where noted, evaluations of operands of individual operators and of subexpressions of individual
expressions are unsequenced. [Note: In an expression that is evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be
performed consistently in different evaluations. —end note ] The value computations of the operands of an
operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar
object is unsequenced relative to either another side effect on the same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
In this line
cout << y-- << "," << --y;
you've introduced two side effects (increments by postfix and prefix, respectively) and two value computations (results of y-- and --y) on a scalar object (y) where they are unsequenced. Thus, your program is ill-formed and just about anything is a possible output.
Read more about this here.

cout<<y--<<","<<--y; is an expression with two unsequenced side effects on y, and therefore has undefined behavior.

Related

Why is *ptr = (*ptr)++ Undefined Behavior

I am trying to learn how to explain the cause of(if any) of undefined behavior in the following cases(given below).
int i = 0, *ptr = &i;
i = ++i; //is this UB? If yes then why according to C++11
*ptr = (*ptr)++; //i think this is UB but i am unable to explain exactly why is this so
*ptr = ++(*ptr); //i think this is not UB but can't explain why
I have looked at many SO posts describing UB for different pointer cases similar to the cases above, but still i am unable to explain why exactly(like using which point(s) from the standard we can prove that they will result in UB) they result in UB.
I am looking for explanations according to C++11(or C++14) but not C++17 and not Pre-C++11.
Undefined behavior stems from this:
C++11 [intro.execution]/15 Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced... If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
C++17 [intro.execution]/17 Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced... If a side effect on a memory location (4.4) is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent (4.7), the behavior is undefined.
This text is similar. The main difference lies in "except where noted" part; in C++17, the order of evaluation of operands is specified for more operators than in C++11. Thus:
C++17 [expr.ass]/1 In all cases, the assignment is sequenced after the value
computation of the right and left operands, and before the value computation of the assignment expression. The right operand is sequenced before the left operand.
C++11 lacks the bolded part. This part is what makes i = i++ well-defined in C++17, but undefined in C++11. That's because for postfix increment, the side effect is not part of a value computation of the expression:
C++11 and C++17 [expr.post.incr]/1 The value computation of the ++ expression is sequenced before the modification of the operand object.
So "the assignment is sequenced after the value computation of the right and left operands" is not by itself sufficient: the assignment is sequenced after the value computation of i++, and the side effect is also sequenced after that same value computation, but nothing says how they are sequenced relative to each other. Therefore, they are unsequenced, and they are both modifying the same object (here, i). This exhibits undefined behavior.
The addition of "the right operand is sequenced before the left operand" in C++17 means that the side effect of i++ is sequenced before the value computation of i, and both are sequenced before the assignment.
On the other hand, for pre-increment the side effect is necessarily part of the evaluation of the expression:
C++11 and C++17 [expr.pre.incr]/1 ... The result is the updated operand; it is an lvalue ...
So the value computation of ++i involves incrementing i first, and then applying an lvalue-to-rvalue conversion to obtain the updated value. This value computation is sequenced before the assignment in both C++11 and C++17, and so the two side effects on i are sequenced relative to each other; no undefined behavior.
Nothing changes in this analysis if i is replaced with (*ptr). That's just another way to refer to the same object or memory location.
The C++ Standard is based upon the C Standard, whose authors didn't need any particular "reason" to say that implementations may process a construct in whatever fashion would be most useful to their customers [which is what they intended the phrase "Undefined Behavior" to mean]. Many platforms can cheaply guarantee, for small primitive types, that race conditions involving a read and conflicting write to the same object will always yield either old or new data, and that race conditions involving conflicting writes will result every individual subsequent read seeing one of the written values. Rather than trying to identify all of the cases where implementations should or should not be expected to uphold guarantee, the Standard allows implementations to, at their leisure, process code "in a documented manner characteristic of the environment". Because it's not practical for all implementations to offer such guarantees in all possible scenarios, and because the range of scenarios where such guarantees would be practical would be different on different platforms, the authors of the Standard allowed implementations to weigh the pros and cons of offering various behavioral guarantees on their particular target platforms, rather than trying to write precise rules that would be appropriate for all possible implementations.
Note also that if one were to do something like:
*p = (*q)++;
return q[0] + q[i]; // where 'i' is some object of type `int`.
when p and q are equal and i is zero, a compiler might quite plausibly generate code where the assignment would undo the effect of the increment, but which would return the sum of the old value of q, plus 1, plus the actual stored value of q (which would be the old value, rather than the incremented value). Although this would be a logical consequence of the specified race-condition semantics, trying to specify it precisely would have been sufficiently awkward that the Standard simply allows implementations to specify the behavior as tightly or loosely as they see fit.

Is inserting map size as value into a map undefined behavior? [duplicate]

This question already has answers here:
Why does setting an element of a map to its size increments the size *before* assigning it?
(4 answers)
Closed 2 years ago.
edit: this question should have not been closed, if you look at the answers you will see they are totally different(old question has no mention of C++17).
I was reading a PVS blog post where they mention the following bug.
(reduced)
std::map<int,int> m;
m[7]=5;
auto val = 15;
if (!m.contains(val)){
m[val] = m.size(); // bug here
}
According to blog post this is buggy.
I always thought that operator [] call for map is a function call so .size() is sequenced before [] because functions act as sequence point.
So why is this a bug?
note: I know sequence points do not exist since C++11, but I use them since new wording is much harder for me to understand.
Pre C++17
§ 1.9 Program execution [intro.execution] (n3690 c++14 draft)
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are
unsequenced.
and 5.17 [expr.ass] doesn't mention any sequencing between the operands of built-in assignment. So the evaluation of the two operands of the built-in assignment operator = is unsequenced with regards to each other.
m[val] and m.size() can be evaluated in any order (can even overlap - interleaved the CPU instructions).
Considering:
m[val] has a side effect of modifying the map's size (a scalar)
the value computation of m.size() accesses the map's size
§ 1.9 Program execution [intro.execution] (n3690 c++14 draft)
[...] If a side effect on a scalar object is unsequenced relative to either [...] or a value computation using the value of the same
scalar object, the behavior is undefined.
So yes, the behavior is indeed Undefined.
C++17
§8.5.18 Assignment and compound assignment operators [expr.ass] (n4713
C++17 draft)
The assignment operator (=) [...] The right operand is sequenced before the left operand.
So the behavior is defined. m.size() will be evaluated before m[val]

Strange behavior of multiplying a pre-increment variable to itself in c++

sorry if my question is duplicate or not worth answering.
I have been the following code that produces the result that I am not understanding how.
int x=5;
int y;
y = ++x * ++x;
cout<<x <<endl;
cout<<y;
According to my little understanding of programming, the value of y should be 42, but, the output on the computer is 49. Kindly help what will be the output of variable y.
I am executing the code in Dev-C++.
Thanks in advance.
The short answer is that you have an undefined behavior in there.
The exact answer depends on which standard you use.
Pre C++11, we had the notion of sequence points. Intuitively, they are points in which all the values have been properly stored, such as at the end of statement (at the semicolon). The standard says that
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an
expression.
, which means that between 2 sequence points (for the sake of simplicity, read as between 2 semicolons), the value of a variable cannot be changed more than once. You change the value twice, using the increment operator.
C++11 removed the notion of sequence points with relationships of sequenced before, sequenced after or unsequenced, referring to the order in which the expressions are evaluated.
In arithmetic expressions,
If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or [...] the behaviour is undefined.
and there is no sequencing between the operators of an arithmetic expression. Therefore, it is still a case of undefined behavior, just for another reason.
This means in practice that the compiler can choose what to do, and, in your case, it produces the results you observe. You should try to avoid undefined behaviour in your programs as much as possible. Below are some references that expand on the subject:
https://en.cppreference.com/w/cpp/language/eval_order
Undefined behavior and sequence points

c++11 Order of evaluation (undefined behavior)

vec[ival++] <= vec[ival]
This expression has undefined behavior, because the order of evaluation of operator's (<=) operands is undefined.
How can we rewrite that expression to avoid the undefined behavior?
I've found an answer that appears to work:
vec[ival] <= vec[ival + 1]
If that is the right way to avoid the undefined behavior, why does rewriting it that way avoid the undefined behavior?
Adding any reference about how to fix that expression would be great.
Yes, your first example has undefined behavior because we have an unsequenced modification and access of a memory location, which is undefined behavior. This is covered in draft C++ standard [intro.execution]p10 (emphasis mine):
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual expressions are unsequenced.
[ Note: In an expression that is evaluated more than once during the
execution of a program, unsequenced and indeterminately sequenced
evaluations of its subexpressions need not be performed consistently
in different evaluations. — end note  ] The value computations of the
operands of an operator are sequenced before the value computation of
the result of the operator. If a side effect on a memory location
([intro.memory]) is unsequenced relative to either another side effect
on the same memory location or a value computation using the value of
any object in the same memory location, and they are not potentially
concurrent ([intro.multithread]), the behavior is undefined. [ Note:
The next subclause imposes similar, but more complex restrictions on
potentially concurrent computations. — end note  ] [ Example:
void g(int i) {
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the value of i is incremented
i = i++ + i; // the behavior is undefined
i = i + 1; // the value of i is incremented
}
— end example  ]
If we check out the section of relational operators which covers <= [expr.rel] it does not specify an order of evaluation, so we are covered by intro.exection and thus we have undefined behavior.
Having unspecified order of evaluation is not sufficient for undefined behavior as the example in Order of evaluation of assignment statement in C++ demonstrates.
Your second example avoids the undefined behavior since you are not introducing a side effect to ival, you are just reading the memory location twice.
I believe that is a reasonable way to solve the problem, it is readable and not surprising. An alternate method could include introducing a second variable, e.g. index and prev_index. It is hard to come with a fast rule given such a small code snippet.
It avoids undefined behavior because you are not changing the value of ival. The issue you're seeing in the first sample is that we can't determine what the values of ival are at the times that they're used. In the second sample, there's no confusion.
Let's start with the worst problem first, and that is the Undefined Behavior. C++ uses sequencing rules. Statements are executed in seqeuence. Usually that's top-to-bottom, but if statements, for statements, function calls and the like can change that.
Now withing a statement there still might be a further sequence of execution, but I'm very intentionally writing might. By defaults, the various parts of a single statement are not sequenced relative to each other. That's why you can get the varying order of execution. But worse, if you change and use a single object without sequencing, you have Undefined Behavior. That is bad - anything might happen.
The proposed solution (iVal + 1) doesn't change iVal anymore, but generates a new value. That is entirely safe. Still, it leaves iVal unchanged.
You may want to check on std::adjacent_find(). Chances are that the loop you're trying to write is already in the Standard Library.
The first problem is that as the initial code exhibited undefined behavior, under the C++ standard there is no "fix". The behavior of that line of code is not specified by the C++ standard; to know what it is supposed to do you have to have another source of information.
Formally, that expression can be rewritten as system("format c:"), as the C++ standard does not mandate any behavior from a program that exhibits undefined behavior.
But in practice, when you run into something like that, you have to read the original programmer's mind.
Well, you can solve anything with lambdas.
[&]{ bool ret = vec[ival] <= vec[ival+1]; ++ival; return ret; }()
Second,
vec[ival] <= vec[ival+1]
is not the same, because it lacks the side effect of ival being 1 greater after the expression is evaluated.

C + C++ = undefined behavior? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do we explain the result of the expression (++x)+(++x)+(++x)?
Undefined Behavior and Sequence Points
I have the problem, when the code
U = C + C++;
Runs in different way for standart types and for my own types.
I have an example http://ideone.com/4S1uA where I have different values for int and my class Int, which should represent the way real Int works.
Is it possible to make my class behave the same way, as the standard int works? Has this code undefined behavior?
WHY it is undefiend behaivior? C++ has an operation priorities, so the c++ should be evaluated first, as it change the value of a, so for addition as first argument should be passed new value of a and as the second the old value. And it's works this way for class Int, but not for standart int.
Has this code undefined behavior?
Yes. The order in which the operands are evaluated, with respect to the side effect, is undefined.
Section 6.5(2) of the standard says:
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.
Since int is a scalar type, and since the side effect here is unsequenced, the behavior is undefined.
You should write your code like this:
U = 2*C;
C++;
Yes, that is undefined behavior. You can't access a variable twice in a statement that also modifies it because the order in which the expression 'C' and the expression 'C++' are evaluated is not defined.
The concept involved here is one of sequence points. To quote the opening sentence from the Wikipedia article:
A sequence point in imperative programming defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.
In C, the + operator does not create a sequence point. Therefore the order of side effects is not defined. However, in C++, an overloaded operator + is a function call, which does create a sequence point. This creates different behavior with respect to side effects. Note that while the order in which function arguments are evaluated is not specified, all side effects are completed before the function enters. So if C + C++ involves an overloaded + operator, then the C++ side effect will have been applied to the left argument of + before the + function executes. This is unlike the case for int values, where the left side may or may not be evaluated before the side effect of the right side is complete.