Suppose that on a C implementation (e.g. on a x86 C compiler) USHRT_MAX = 65535
and INT_MAX = 2147483647
. Is, then, the following statement well-defined?
unsigned short product = USHRT_MAX * USHRT_MAX;
According to the following in the C99 standard both operands are promoted to int
(since int
can represent all possible values of unsigned short
) and, therefore, the result is not well-defined, since an overflow will occur (65535 ^ 2 = 4294836225 > 2147483647
), which means that the value of product
is not well-defined:
6.3.1.1-1
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.(48) All other types are unchanged by the integer promotions.
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.
However, according to the following, the result is well-defined, since computations involving unsigned operands do not overflow:
6.2.5-9
The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type, and the representation of the same value in each type is the same.(31) A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
Does the variable product
in the aforementioned statement have a well-defined value?
EDIT: What should happen in the following case?
unsigned short lhs = USHRT_MAX;
unsigned short rhs = USHRT_MAX;
unsigned short product = lhs * rhs;
int
for arithmetic, the rules are just too confusing to allow for mortal programmers to write correct code... - Steve Jessopint
will occur irrespective of whether you use a constant or a variable. - Alexey Frunzeint
in the first case.USHRT_MAX
as given is anint
. The whole picture would change if it would be declared as65535U
. - Jens GustedtUSHRT_MAX
has the same type as it would have if there were a promotion (and hence it would have typeunsigned int
on some hypothetical implementation in whichshort
andint
are the same width). Good spot. - Steve Jessop