In article <DI******************************@comcast.com>
Ark <ak*****@macroexpressions.comwrote:
>char c;
short s;
unsigned u;
long l;
If I am not mistaken in this wee hour;
u+l means (long)u+l even if sizeof(unsigned)==sizeof(long)
s+u means (unsigned)s+u even if sizeof(unsigned)==sizeof(short)
c+s means (int)c+(int)s
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.