Frederick Gotham wrote On 06/09/06 16:59,:
Ben Pfaff posted:
Is there any sort of guide I can read which would show me when and why
integer promotion happens?
Well, there's the Standard ...
Informally, when a "narrow" integer is used as an operand
or is passed to a function without a prototype or is passed as
one of the "..." arguments to a variable-argument function,
the value is first promoted to int or to unsigned int. But
let's not rush ahead: First, what's a "narrow" type?
Formally, the types subject to promotion are those whose
"rank" is less than that of int. Informally, these are the
types with "fewer bits" than int: char and short (on most
systems), bit-fields with small widths, and all of these in
both signed and unsigned flavors. If the compiler decides not
to use full-sized ints for some enum types, they are also
subject to promotion. In C99, the promotable list adds _Bool
and perhaps some implementation-defined narrow types that the
Standard doesn't enumerate.
All right, those are the types that get promoted. What
do they get promoted to? The rule is straightforward:
- If all the possible values of a "narrow" type can be
represented by an int, the type promotes to int.
- Otherwise, the type promotes to unsigned int.
The potentially tricky part is that stuff about ranges,
because the range of values a particular type can represent is
up to the implementation (subject to some requirements), and
the ranges vary from one implementation to another. Let's
work through a few examples.
First, an easy one: What happens to a short? The range
of short can be different on different implementations, but
we know it will never be wider than the range of the same
implementation's int: Every short value is also a legitimate
int value. Therefore, short always promotes to int, on every
C implementation everywhere. That wasn't so bad, was it?
How about unsigned short? Now things get tougher. On
many systems an int has 32 bits and an unsigned short has 16.
On these systems, every unsigned short value is also an int
value, so unsigned short promotes to int. But what about a
system where int and short are both 16 bits wide? On such
systems INT_MAX will be 32767 but USHRT_MAX will go all the
way up to 65535, so there exist unsigned short values that
are too large for int. On these systems, unsigned short will
promote to unsigned int.
Similar issues arise with other narrow types: you usually
know that they are "narrow," but not what they'll promote to.
Even the lowly char promotes to int on some systems and to
unsigned int on others -- yes, Virginia, there are systems
where char and int have the same bit count, and if char is
unsigned (remember, the signedness of char is also at the
discretion of the implementation) CHAR_MAX will be equal to
UCHAR_MAX and both will be bigger than INT_MAX.
Why does C introduce all this confusion about promotion?
Hard to say for certain, but the confusion is probably an
attempt to make things simpler. ("Say, what?") Consider:
The underlying hardware probably doesn't have an instruction
that multiplies an unsigned short by a signed bit-field of
width eleven. Yet the language allows you as a programmer
to write such an expression, so what is the compiler to do
with it? C's answer is to promote the values to some flavor
of int, the machine's "natural" word size and the one most
likely to be supported best by the instruction set.
As a language, C is fairly close to the hardware. The
matter of promotion is one place where the hardware becomes
more visible to the programmer than it is elsewhere, and
sometimes more troublesome, too.