Brice said:
Brice said:
[...]
I found info on IBM site:
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?top...
I understand that all operands of an expression are converted to the
type of the largest one.
Sort of, and not "globally." That is, in the second line of
double f = 98.6;
double c = 5 / 9 * (f - 32);
"the largest one" is double, yet the sub-expression `5 / 9'
is evaluated with int arithmetic (and has the value zero).
The promotion rules apply "one operator at a time."
Thanks Eric, this is exactly the kind of situation I was looking for.
May I say that it works like this?
1) the compiler starts with the left-most operator after the equal
sign,
No. Operators group according to their precedence and
associativity (really, according to the formal grammar of the
language), so the leftmost operator is not necessarily the
first one considered. In `x = a + b / c' the leftmost-after-
equals operator is `+', but `b / c' is evaluated independently,
uninfluenced by `a' and `+'.
Also, there may not even *be* an equal sign involved, as in
`if (x < 2 * y)' or `return a + b / c;'.
checks the type of both operands and operator specific rules, to
decide
the type and value of the result. In that case:
int divided by int gives int, here 0.
2) carries on with next operation following the same rules:
f-32 is double minus int, so the result is double 66.6
(int) 0 times (double) 66.6 which yields (double) 0
3) And finally converts to lvalue type, in this case no conversion
because double on both sides.
Which is tricky because one could expect all operands to be converted
to
double before hand... I am not sure why it is not the case, but I am
sure
there must be a reason.
Think of it this way: Expressions are evaluated "bottom-up."
The rules of precedence and associativity (really, the formal
grammar of the language) decompose a long expression into sub-
expressions and sub-sub-expressions and so on until you get down
to "atoms" like variables and constants. Then the expression is
re-composed in the same pattern, combining operands by operating
on them with their operators. As each operator in turn is handled,
its own operands are promoted as necessary.
So, let's look at my example again and try to pick apart
the second line:
double f = 98.6;
double c = 5 / 9 * (f - 32);
The right-hand side `5 / 9 * (f - 32)' is an expression that
contains three operators. Thanks to the grammar, we know
it is composed as
[*]
|
---- [/]
| |
| ---- [5]
| |
| ---- [9]
|
---- [-]
|
---- [f]
|
---- [32]
or (* (/ 5 9) (- f 32)) for LISPers. We don't know whether
`5 / 9' or `f - 32' is evaluated first (order of evaluation
is another topic altogether), but we know that it goes like
5 / 9 is int / int. The operand types match so no
promotions are needed, and the calculation is done
according to int rules, yielding an int with the
value zero.
f - 32 is double - int. There's a mismatch in the
operand types, so the int is promoted to a double and
we have f - 32.0, double - double. The calculation
is then done according to double rules, yielding a
double with the value 66.6
Finally, 0 * 66.6 is int * double. Again there's a
mismatch, and again the int is promoted to double and
we have 0.0 * 66.6. The calculation is done according
to double rules, yielding 0.0 as its double result.
I just want to know exactly what's going on.
A worthwhile objective.
When
in doubt I always cast. So far so good, at least as far as I can
tell...
Instead of "always cast," I'd encourage you to become more
familiar with the way the language operates. It's a tool, and
muttering half-understood incantations is not the best way to
get it to cut the workpiece instead of your finger.