Using post-increment arguments in a function

When I run this code, the output is 11, 10.

Why would this be so? Can someone give me an explanation for this that hopefully enlightens me?

thanks

#include <iostream> using namespace std; void print(int x, int y) { cout << x << endl; cout << y << endl; } int main() { int x = 10; print(x, x++); } 
+6
source share
4 answers

C ++ standard (note in section 1.9.16):

Calculation of values ​​and side effects associated with various expressions of arguments have no consequences.

In other words, it is undefined and / or dependent on the compiler, which orders the arguments, are evaluated before their value is passed to the function. Therefore, on some compilers (which evaluate the left argument first), the code will output 10, 10 , and on others (which evaluate the right argument first), it will output 11, 10 . In general, you should never rely on undefined behavior.

To help you understand this, imagine that each expression of an argument is evaluated before the function is called like this (not the way it actually is, it's just an easy way to think about it, which will help you understand the sequence):

 int arg1 = x; // This line int arg2 = x++; // And this line can be swapped. print(arg1, arg2); 

The C ++ standard says that two arguments to an expression are not affected. So, if we write out the expressions of arguments in separate lines, like this, their order should not be significant, because the standard says that they can be evaluated in any order. Some compilers may evaluate them in the above order; others may change them:

 int arg2 = x++; // And this line can be swapped. int arg1 = x; // This line print(arg1, arg2); 

This makes it pretty obvious how arg2 can hold a value of 10 and arg1 contains a value of 11 .

You should always avoid this undefined behavior in your code.

+12
source

Overall statement:

  print(x, x++); 

leads to undefined behavior . Once a program has Undefined Behavior, it ceases to be a valid C ++ program, and literally any behavior is possible. Therefore, it makes no sense to find reasoning for such a program.


Why is this behavior undefined?

Allows you to evaluate the program step by step to such an extent that we can, without a doubt, prove that it causes Undefined Behavior .

The evaluation order of the arguments to the Unspecified [Ref 1] function.

Unspecified means that implementations are allowed to implement this particular functionality at their discretion, and there is no need to document details about it.

Applying the above rule to a function call:

 print(x, x++); 

An implementation can evaluate this as:

  • From left to right or
  • Right left or
  • Any magic order (in the case of more than two function arguments)

In short, you cannot rely on an implementation to follow any particular order, because it is not required by the C ++ standard.

In C / C ++, you cannot read or write a variable more than once without an intermediate point [Ref 2] . If you do this, it will result in an Undefined Behavior. Regardless of whether one of the arguments is evaluated first in the specified function, there is no sequence point between them, the sequence point exists only after evaluating all the arguments of the function [Ref 3] .

In this case, x accessed without an intermediate point in the sequence and, therefore, leads to Undefined behavior.

Simply put, it’s better to write any code that doesn’t call such Undefined Behaviors , because after that you cannot expect any specific behavior from such a program.


[Ref 1] C ++ 03 Standard Β§5.2.2.8
Paragraph 8:

[...] The procedure for evaluating function arguments is not specified . [...]


[Ref 2] C ++ 03 5 Expressions [expr]:
Paragraph 4:

....
Between the previous and next points in the sequence, the scalar object must have the value of the stored value, changed no more than once by evaluating the expression. In addition, the previous value should only be accessed to determine the value to be stored . The requirements of this section are satisfied for each admissible ordering of the subexpressions of the full expression; otherwise, the behavior is undefined .


[Link 3] C ++ 03 1.9 Execution of the program [intro.execution]:
Paragraph 17:

When a function is called (regardless of whether the function is built-in), a sequence point appears after evaluating all the arguments of the function (if any), which is performed before any expressions or operators are executed in the function body.

+6
source

x ++ is a function parameter, and they can be evaluated in an unspecified order, which means that the behavior is undefined and not portable (or legal).

+4
source

I believe this is due to the function call stack, in which the last argument comes first. So x ++ is your y, and x is the local x in print ().

0
source

Source: https://habr.com/ru/post/918231/


All Articles