Regards,
Sarathy
These rules are made so that C programmers capable of writing robust
arithmetic expressions (or better yet, portable ones) could command big
bucks :)
I just gave a very loose explanation in
<4kh9lgF...@individual.net>
As this is IMO one of the topics that are presented rather
readable in the standard text, I suggest that you have a look
at "n1124.pdf" (just google for it), section 6.3.
Note that this is the current C99 standard plus technical
corrigenda -- C90 did behave a little bit different when it
came to the usual arithmetic conversions for operations involving
floating point operands and had no long long type.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
That's not what integer promotion is.
Integer promotion can only result in an expression
of either type int or type unsigned.
sizeof(c + c) == sizeof(u)
--
pete
48) The integer promotions are applied only: as part of the usual
arithmetic conversions, to certain
argument expressions, to the operands of the unary +, -, and ~
operators, and to both operands of the
shift operators, as specified by their respective subclauses.
Alas, you are mistaken. The ANSI/ISO rules are terribly complicated
by depending on the relative values of the corresponding MAXes.
Consider the "u+l" case for a moment. Suppose we are on a typical
32-bit machine, with 32-bit int and 32-bit long, and hence both
INT_MAX and LONG_MAX are 2147483647 while UINT_MAX is 4294967295.
The ANSI "value-preserving" rule says that widening a narrower
signed type produces a new, wider signed type if and only if the
relative *_MAX is not exceeded. Otherwise, it produces a new,
wider unsigned type.
Since UINT_MAX exceeds LONG_MAX, widen(u) produces unsigned long,
instead of signed long. We then have (unsigned long) + (signed long);
the second "signed" long is converted to "unsigned", and the addition
is done with unsigned arithmetic -- where overflow is discarded --
and the result has type "unsigned long".
If LONG_MAX is greater than UINT_MAX, however, widen(u) produces
signed long. We then have (signed long)+(signed long); the addition
is done in signed arithmetic (overflow giving undefined behavior)
and the result has type "signed long". This is the case on a
typical 64-bit machine (32-bit int, 64-bit long).
(See also the appended test code.)
>signed promotion is value-preserving;
This is correct: it preserves the value if possible (if the new
wider type has a lower *_MAX, we hit a snag; but this case is either
completely ruled out by the Standard, or else at least never seems
to occur in practice; I am not sure which). (C89 and C99 have
somewhat different wording, in part because C99 now has "long long"
as well.)
>promotion to an unsigned type preserves the bit pattern.
This is only true for two's complement systems. On a Univac, you
get some interesting code.
[test code]
#include <stdio.h>
long l;
unsigned u;
void f0(void) { if (u + l > 0) puts("u + l is unsigned"); }
void f1(void) { if ((long)u + l > 0) puts("(long)u + l is unsigned"); }
void f2(void) { if (u + (unsigned)l > 0) puts("u + (unsigned)l is unsigned"); }
int main(void) {
u = -1U, l = -1L; /* -1L + -1L = -2L */
f0();
f1();
f2();
return 0;
}
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
This explanation is quite good, but I have a quibble.
For promotions, there is a notion of widening. For
binary operators though, both operand types participate
in finding a common real type and both operand values
are converted to that type. It isn't that we "widen"
one type and convert the other - both operands are
simply converted (and indeed no widening may take
place even when the conversion ranks are different).
Don't get me wrong, I like the explanation; I just
think it could be better if couched in language
more closely parallel to how language in the Standard
expresses it.