2

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.

Community
  • 1
  • 1
Seagull
  • 3,319
  • 2
  • 31
  • 37
  • 5
    Yes, it's undefined behavior. I'll let someone else create an answer with references to the standard, etc. – Mark Ransom Feb 10 '12 at 20:45
  • 1
    See http://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviour-that-a-c-programmer-should-know-ab – Dervall Feb 10 '12 at 20:46
  • 1
    Yes, it is UB because it is undefined whether `C` or `C++` will be evaluated first. – Ed S. Feb 10 '12 at 20:46

3 Answers3

4

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++;
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I can't imagine the situations when construction `c + c++` is needed, but I have some debates on how this code should work. But 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 new value changed and as the second the old value. But this doesn't work for build in types. – Seagull Feb 10 '12 at 20:53
  • 2
    The order in which the operands are evaluated is undefined. – David Heffernan Feb 10 '12 at 20:56
  • 3
    @Seagull: This isn't an issue of operator precedence. Yes, the ++ operation happens before the + operation(due to precedence), but that doesn't tell you when the value of C is evaluated for the left hand side of that + operation. – Benjamin Lindley Feb 10 '12 at 20:58
  • The `c++` must be evaluated before the call of addition. As my class has two parameters passed by references, so it will work with new and old values and its behaivior is defiened. But for build in types we don't have information about how the addition is performed so we don't know which operand is evaluated first. Am I right? – Seagull Feb 10 '12 at 21:02
  • Not quite. The compiler must do three things while evaluating C + C++. First, it has to find the value of C, then it must find the value of C++, then add them. The issue is that the _order_ of the first two steps is not defined, no matter the type. This expression is -never- defined, you're just getting lucky with your types. – Collin Feb 10 '12 at 21:29
  • Phrased differently: Operator precedence simply states that the expression is grouped as `((c) + (c++))`. Of course, the operands of the addition must be known before we can actually do the addition, so `c` and `c++` need to be evaluated. However, we cannot say which of these operands is evaluated first. Do we find out what `c` is first and then `c++`, or the other way around? Depending on this order, the increment will effect the result of the addition. We cannot determine what order this will be. – Joseph Mansfield Feb 10 '12 at 21:59
2

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.

Collin
  • 11,977
  • 2
  • 46
  • 60
2

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.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • `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` No, `f(c, c++)` is also UB for scalar c. – Cubbi Feb 10 '12 at 21:14
  • @Cubbi - I didn't say that the behavior is necessarily defined. I said that before `+` executes the `++` side effect will have completed (unlike with the built-in `+` operator, which does not create a sequence point). For scalars, obviously the order of argument evaluation (which is UB) determines what values are passed to the function. For objects, the point is that what `+` sees as the left argument is guaranteed to include the effects of the `++`. – Ted Hopp Feb 12 '12 at 19:00