why do we add "d"in the end of a double?

WBahn

Joined Mar 31, 2012
33,075
The ordering operands is to make the order of the side effects predictable. For instance, if each of the operands is a function call, and the functions have side effects, then you cannot change the order in which those functions are called.

However, you can evaluate the operands, assign the results to registers or temps, then evaluate the expression from those temps in any order that produces the correct value.
This approach is allowed by the C language standard, and perhaps many others. In the C spec, it is explicitly stated that this is allowed. But it makes no distinction on whether the operands have side effects or not, thus the same code can (and often does) produce different results depending on the compiler used. The language spec defines sequence points and requires that all assignments be made and side-effects resolved before proceeding beyond the sequence point. But the order in which things happen between sequence points is unspecified -- it does not even have to be specified by the implementation.

But we are talking about the C# spec here and my question is whether the C# spec specifies the order of evaluation of subexpressions.
 
Last edited:

BobTPH

Joined Jun 5, 2013
11,616
I don’t see why it would since it cannot change the behavior of any program if you do what I say.

I was giving a rationale for specifying the order of the operands and not the operators.
 

WBahn

Joined Mar 31, 2012
33,075
I don’t see why it would since it cannot change the behavior of any program if you do what I say.

I was giving a rationale for specifying the order of the operands and not the operators.
But I am not asking for a rationale for what could be the case or whether there is an apparent reason why the language standard requires something or whether it would be fine if it does what you say. None of that matters. What matters is what the language spec for C# ACTUALLY specifies. Not what we think it should, not what we think it might, but what it does. Just as testing some code on a compiler does not confirm what the language spec says, neither does speculating about it.

I've been digging into the C# language spec a bit deeper. Unfortunately, since it is not a single document but rather a bunch of hyperlinked pages, it is not easy for me to search for the terms I am looking for.

This is what I have found so far:


Section 11.4.1 said:
Operands in an expression are evaluated from left to right.
Example: In F(i) + G(i++) * H(i), method F is called using the old value of i, then method G is called with the old value of i, and, finally, method H is called with the new value of i. This is separate from and unrelated to operator precedence. end example
Without this, this statement would invoke undefined behavior -- and this is EXACTLY what happens in C, perfectly in conformance with the C language standard.

The only other place I've found that touches on it is from the language reference (and NOT the specification).

Operand evaluation
Unrelated to operator precedence and associativity, operands in an expression are evaluated from left to right. The following examples demonstrate the order in which operators and operands are evaluated:

ExpressionOrder of evaluation
a + ba, b, +
a + b * ca, b, c, *, +
a / b + c * da, b, /, c, d, *, +
a / (b + c) * da, b, c, +, /, d, *
Typically, all operator operands are evaluated. However, some operators evaluate operands conditionally. That is, the value of the leftmost operand of such an operator defines if (or which) other operands should be evaluated. These operators are the conditional logical AND (&&) and OR (||) operators, the null-coalescing operators ?? and ??=, the null-conditional operators ?. and ?[], and the conditional operator ?:. For more information, see the description of each operator.
So the question is, per the language spec, which of the following evaluation orders allowed:

(a + b) / (c - d) // a, b, +, c, d, -, /
(a + b) / (c - d) // a, b, c, d +, -, /
(a + b) / (c - d) // a, b, c, d -, +, /

The examples IMPLY that operators will be executed as soon as their operands are evaluated. If this is true, then the the bottom two would be eliminated. But it might still be possible to construct an expression where there is still ambiguity.

Part of the ambiguity (possible all of it) resides in what the definition of "operand" is. Unfortunately, the spec does not define this, but rather appears to use the definition in ISO/IEC 2382.1, which appears to require a subscription to access.

I have found a couple of C# websites that state that an operand is a literal or a variable. But, of course, this is not definitive. However, if this is the case, then (a + b) and (c-d) would not be considered operands (for the / operator), and hence their order of evaluation would be undefined (based on what I've found in the spec thus far).

But the section from the spec seems to be at odds with this because it states not only that i, i++, and i will be evaluated in that order, but that the function calls will also be evaluated in a specific order.

This would still allow the first two evaluation orders to be acceptable.

I'm still pretty sure (but can't yet find it in the spec) that only the first one is actually allowed by the spec. This is based on the fact that it is my understanding that the C# spec was intentionally meant to eliminate as much unspecified behavior as they could wring out of it.
 
Top