In a C implementation where int
can hold all values of type unsigned short
, standard integer promotion rules dictate that given the code:
unsigned short x=(USHORT_MAX+1)-3; // Or just -3
x*=x;
a compiler should evaluate the latter statement as equivalent to x=(unsigned short)((int)x * (int)x);
. Even though unsigned values are nominally supposed to behave according to the rules of modular arithmetic, the standard imposes no requirements upon the behavior of such a statement when x
exceeds sqrt(INT_MAX), and a compiler could legitimately specify a behavior other than computing a result as if the computation were performed in unsigned fashion in the destination type. Has any historical C implementation ever specified, in cases where the result of integer operators other than >>
, %
, and /
is coerced to an unsigned type smaller than int
, a behavior contrary to what would be yielded if the operands were coerced to, and computation were performed in, the destination type?
On a related note, how many “classical” C compilers have there been which, given code like the above, might plausibly have failed to compute 9? A two’s-complement machine would get that result if it simply ignored any overflow in the multiply, but a sign-magnitude machine which attempted to perform the computation using signed integer math could not. On the other hand, having compilers look at how an expression will be used when deciding how to evaluate it has been a longstanding practice in many C compilers, and a compiler could easily observe that if arithmetic is being performed on non-negative values and the result is being coerced to unsigned short, the standard would allow unsigned values to be substituted, avoiding any need for sign-handling logic.
22