Velocity Reviews > integral promotion, arithmetic conversion, value preserving, unsigned preserving???

# integral promotion, arithmetic conversion, value preserving, unsigned preserving???

TTroy
Guest
Posts: n/a

 01-28-2005
Hello, I'm relatively new to C and have gone through more than 4 books
on it. None mentioned anything about integral promotion, arithmetic
conversion, value preserving and unsigned preserving. And K&R2
mentions "signed extension" everywhere.

Reading some old clc posts, I've beginning to realize that these books
are over-generalizing the topic. I am just wondering what the
difference between the following pairs of terms are:

1) Integral promotion vs. Arithmetic Conversion
2) Value Preserving vs. Unsigned Preserving

I've read many, many old posts from c.l.c that referred to those 4
terms constantly.. this is what I think they mean:

Integral Promotion
===================
All chars and shorts are promoted to int(signed) before any operating
is done on them. If an unsigned short has the same bit-size as int,
then the promotion is to unsigned int.

Integral promotion is done as an intermediate step for all common
computations.

Ex:

char a = 9;
unsigned b = 4;

a = b + a; /* a and b both converted to int before addition */
/* the result is then converted back to char by the assignment */

So basically, integral promotion gurantees that all intermediate
computations are dealt with nothing "lower" than an int. Am I right?

-
Artihmetic Promotion
=====================
If the variables involved in an arithmetic operation are all at least
int, then "level" priorities take over.

The priority is : long double, double, float, long, int

If one variable involved in a binary operation is a higher "level" than
the other, the other is promoted to that same level.

After that, the next type of priority is also applied, based on
signed/unsigned.
If one variable is unsigned and the other is signed, the signed is
converted to unsigned.

Once all this is done, we go on with the binary operation to produce
the result. Am I right?

-
Value Preserving
================
I am very confused on this term. Does it mean that, say for example, a
conversion from an unsigned short to an int is done, and the value
stored in the unsigned short is larger than the maximum possible
positive number in an int, then the result is implementation defined.
If the value stored in unsigned short is less than the maximum
posssible positive number in an in, then the exact value will exit in
the int (guaranteed to have msb = 0).

What I don't get about value preserving rules is, whether they are
based on the actual value in variables(run time), or the POSSIBLE
RANGES of the INTEGERS(compile time)?

-
Unsigned Preserving
===================
I have a feeling this is a more strict rule (subset of Value
preserving) that implies 2's compliment. Where actual bit patters are
moved without change, as would be the case for 2's compliment.
-

Many many posts on these subjects have gone through clc's servers, but
they all deal with subsets of what I'm presenting here. If someone
could make a more comprehensive response (or possible add it to the FAQ
website), I think that would be a major help (especially when books
only mention "signed extension".. some don't mention anything.. they
just say "the value is converted"... looked at C89 draft.. little too

By the way, if one of you clc regulars write a book on C as thorough as
the responses you give, it would force all these phony book authors
into extinction.

[Many of the programmers at my workplace (where I'm an electronics guy)

Richard Bos
Guest
Posts: n/a

 01-28-2005
"TTroy" <(E-Mail Removed)> wrote:

> Integral Promotion
> ===================
> All chars and shorts are promoted to int(signed) before any operating
> is done on them. If an unsigned short has the same bit-size as int,
> then the promotion is to unsigned int.

Ditto for unsigned char. It's a rare occasion outside freestanding
implementations, though.

> char a = 9;
> unsigned b = 4;
>
> a = b + a; /* a and b both converted to int before addition */
> /* the result is then converted back to char by the assignment */
>
> So basically, integral promotion gurantees that all intermediate
> computations are dealt with nothing "lower" than an int. Am I right?

Yes. Unfortunately - I don't like this "feature".

> Artihmetic Promotion
> =====================
> If the variables involved in an arithmetic operation are all at least
> int, then "level" priorities take over.
>
> The priority is : long double, double, float, long, int
>
> If one variable involved in a binary operation is a higher "level" than
> the other, the other is promoted to that same level.
>
> After that, the next type of priority is also applied, based on
> signed/unsigned.
> If one variable is unsigned and the other is signed, the signed is
> converted to unsigned.
>
> Once all this is done, we go on with the binary operation to produce
> the result. Am I right?

Half. What you've written is correct; but there are similar promotions
for the floating point types.

Richard

Kobu
Guest
Posts: n/a

 01-29-2005

Richard Bos wrote:
> "TTroy" <(E-Mail Removed)> wrote:
>
> > Integral Promotion
> > ===================
> > All chars and shorts are promoted to int(signed) before any

operating
> > is done on them. If an unsigned short has the same bit-size as

int,
> > then the promotion is to unsigned int.

>
> Ditto for unsigned char. It's a rare occasion outside freestanding
> implementations, though.
>

Integral Promotion

A char or a short (signed or not) may be used in an expression whenever
an integer may be used. If an int can represent all the values of the
original type, then the value is converted to int; otherwise the value
is converted to unsigned int.

=> To add to the OP: When this conversion is done, how many integral
variables are taken into consideration for the promotion at a time, and
what exactly "expression" means is what all explanations lack.

For example (sizeof(short)== 32, sizeof(int) == 32):

unsigned short a = -1;
signed short b = 45;
signed char c = -34;
unsigned char d = 21;
signed long f = SLONG_MAX;
int = e;

e = (a*b + c*d) * f;

Are all a,b,c,d considered against the intergral promotion rule at
once? Or is a&b treated as an independent promotion from c&d? Are all
integral promotions in the whole expression finished before any further
conversions (based on arirthmetic rules)? These are some of the
questions for which I haven't found enlightenment in K&R2 or the
standards (not experienced enough to make much sense of the standards).

Peter Nilsson
Guest
Posts: n/a

 01-29-2005
Kobu wrote:
> Richard Bos wrote:
> > "TTroy" <(E-Mail Removed)> wrote:
> >
> > > Integral Promotion
> > > ===================
> > > All chars and shorts are promoted to int(signed) before any
> > > operating is done on them. If an unsigned short has the same
> > > bit-size as int, then the promotion is to unsigned int.

No. The standard says...

"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."

Bit size is irrelevant. It's the _value_ range that is significant.

> > Ditto for unsigned char. It's a rare occasion outside freestanding
> > implementations, though.

It's arguable whether a hosted implementation where
INT_MAX < UCHAR_MAX could ever be conforming.

> Integral Promotion
>
> A char or a short (signed or not) may be used in an expression
> whenever an integer may be used. If an int can represent all the
> values of the original type, then the value is converted to int;
> otherwise the value is converted to unsigned int.
>
> => To add to the OP: When this conversion is done, how many
> integral variables are taken into consideration for the promotion
> at a time, and what exactly "expression" means is what all
> explanations lack.
>
> For example (sizeof(short)== 32, sizeof(int) == 32):

You have a machine with 32 byte integers! Whatever the size,
the range of integer types is constrained, but _not_ determined
by the size of the integer.

The expression...

sizeof(short) > sizeof(int)

....can theoretically evaluate to 1 on a hypothetical conforming
implementation.

> unsigned short a = -1;
> signed short b = 45;
> signed char c = -34;
> unsigned char d = 21;
> signed long f = SLONG_MAX;

If you meant LONG_MAX, the later expression is a bad example
since the overflow results in undefined behaviour.

> int = e;

ITYM int e;

>
> e = (a*b + c*d) * f;
>
> Are all a,b,c,d considered against the intergral promotion rule at
> once?

Yes.

> Or is a&b treated as an independent promotion from c&d? Are all
> integral promotions in the whole expression finished before any
> further conversions (based on arirthmetic rules)?

Effectively, yes. Though an implementation can achieve this in
various ways behind the scenes. [For instance, for the above
expression, a given compiler may silently convert all the arguments
to long before performing any arithmetic operation, if it can
determine that this act won't change a required result.]

--
Peter

S.Tobias
Guest
Posts: n/a

 01-29-2005
TTroy <(E-Mail Removed)> wrote:

> difference between the following pairs of terms are:

> 1) Integral promotion vs. Arithmetic Conversion
> 2) Value Preserving vs. Unsigned Preserving

Integral promotions deal only with one type and convert (one) short
type to int type. Arithmetic conversions always deal with two types
and convert (one or both) the "smaller" type to the "larger" type (their
purpose is to establish common type for the operands and the result).

> I've read many, many old posts from c.l.c that referred to those 4
> terms constantly.. this is what I think they mean:

> Integral Promotion
> ===================
> All chars and shorts are promoted to int(signed) before any operating
> is done on them.

All short types, to signed or unsigned int, and only in certain cases,
not everywhere.

> If an unsigned short has the same bit-size as int,
> then the promotion is to unsigned int.

Yes. ("Bit-size" is called width.)

> Integral promotion is done as an intermediate step for all common
> computations.

> Ex:

> char a = 9;
> unsigned b = 4;

> a = b + a; /* a and b both converted to int before addition */

Only a is promoted.

> /* the result is then converted back to char by the assignment */

Yes, but this time this conversion is neither promotion nor usual
arithmetic conversion (UAC).

Perhaps more interesting case is this one:
char c;
long l;
c + l;
First c is promoted to (signed or unsigned) int type, and then UAC takes
place and c is converted again to (signed or unsigned) long type.

> So basically, integral promotion gurantees that all intermediate
> computations are dealt with nothing "lower" than an int. Am I right?

Basically yes.

> -
> Artihmetic Promotion
> =====================

You mean: Usual arithmetic conversion.

> If the variables involved in an arithmetic operation are all at least
> int, then "level" priorities take over.

> The priority is : long double, double, float, long, int

For integer types the "level" is called "rank". Into the above list
you could throw in long long and extended types.

> If one variable involved in a binary operation is a higher "level" than
> the other, the other is promoted to that same level.

Yes. And you should use "converted"; the word "promoted" is reserved...
well... for promotions of course.

> After that, the next type of priority is also applied, based on
> signed/unsigned.

No, this is done at the same time. See below.

> If one variable is unsigned and the other is signed, the signed is
> converted to unsigned.

No. This rule is called "unsigned preserving" (aka "signedness preserving")
and was rejected for the "value preserving" rule. See below.

> Once all this is done, we go on with the binary operation to produce
> the result. Am I right?

Yes.

> -

Value and unsigned preserving conversion rules apply both to promotions
and UACs, so we have to consider them together. (Of course, they
apply only to integer types for only they have signedness property).
They are two options of how to perform conversions between signed and
unsigned types. The Standard has chosen value preserving, and rejected
unsigned preserving rule.

Unsigned preserving rule
Whenever one operand is unsigned, all operands are converted to unsigned
version of the target type.
eg.:
promotion:
signed char -> int
unsigned char -> unsigned int
UAC:
unsigned int + long -> unsigned long + unsigned long
Unsigned preserving rule seems simpler and more predictable, but
the Standard has rejected it and it has never applied (only before
the Standard, it's in K&R1).

Value preserving rule
This rule works mostly the same as in unsigned preserving, with one
exception: when the "smaller" type is unsigned and the "larger" type
is signed.
promotion:
unsigned char -> (signed/unsigned) int
UAC:
unsigned int + long -> (s/u) long + (s/u) long
The rule says that:
if range(unsigned shorter) c range(signed longer)
convert (unsigned shorter) to (signed longer)
otherwise
convert both to (unsigned longer).
(range(type) is set of all possible values of type, 'c' means inclusion.)
(Note that in the first case the conversion unsigned->singed is well
defined, cf. 6.3.1.3.)

To illustrate this rule graphically (promotion only):

USHRT_MAX
-I--------------0---S-------------I---> promote short to int
INT_MIN INT_MAX

USHRT_MAX
-------I--------0--------I--------S---> promote short to unsigned
INT_MIN INT_MAX

Value preserving rule is what the Standard has chosen since the beginning.

Which of these rules is better is a matter of past discussions.
No doubt, "value unsigned preserving Chris Torek" are the best
keywords to find them. I don't have my opinion on this issue yet.

> Value Preserving
> ================
> I am very confused on this term. Does it mean that, say for example, a
> conversion from an unsigned short to an int is done, and the value
> stored in the unsigned short is larger than the maximum possible
> positive number in an int, then the result is implementation defined.
> If the value stored in unsigned short is less than the maximum
> posssible positive number in an in, then the exact value will exit in
> the int (guaranteed to have msb = 0).

When USHRT_MAX > INT_MAX, then promote to unsigned.
If USHRT_MAX <= INT_MAX, promote to int.
This is not implementation defined. The width of types is implementation
defined, so we may say that the result is indirectly implementation
defined, but it strictly depends on the ranges of both types.

> What I don't get about value preserving rules is, whether they are
> based on the actual value in variables(run time), or the POSSIBLE
> RANGES of the INTEGERS(compile time)?

Of course, possible ranges.

> -
> Unsigned Preserving
> ===================
> I have a feeling this is a more strict rule (subset of Value
> preserving)

It's not a subset, both rules are mostly the same, they differ
only at one point.

> that implies 2's compliment.
> Where actual bit patters are
> moved without change, as would be the case for 2's compliment.

Neither rule concerns the representation. Unsigned preserving demands
only that "unsigned" always wins, ie: unsigned + long -> both
to unsigned long, always and without exception.

> -

[snip]
> only mention "signed extension"..

"Sign extension" is about converting values (which is part of conversion
operation) in binary representation and it doesn't directly come into
what has been said above. This sort of applies _after_ you have
established what the target type is.

> ... looked at C89 draft.. little too

I know that part (I think of 6.3.1 in C99) is not easy to read,
but it is the most accurate explanation I have come across. Read it
twice a day, after two weeks it'll seem plain obvious to you.

--
Stan Tobias
mailx `echo http://www.velocityreviews.com/forums/(E-Mail Removed)LID | sed s/[[:upper:]]//g`

S.Tobias
Guest
Posts: n/a

 01-29-2005
Peter Nilsson <(E-Mail Removed)> wrote:
> Kobu wrote:

> > unsigned short a = -1;
> > signed short b = 45;
> > signed char c = -34;
> > unsigned char d = 21;
> > signed long f = SLONG_MAX;

> If you meant LONG_MAX, the later expression is a bad example
> since the overflow results in undefined behaviour.

> > int = e;

> ITYM int e;

> >
> > e = (a*b + c*d) * f;
> >
> > Are all a,b,c,d considered against the intergral promotion rule at
> > once?

> Yes.

Of course all promotions can be done at the start, because the
results of arithmetic operators are int or above and there's nothing
to promote afterwards (unless there's a cast to a short type
later on the way).

> > Or is a&b treated as an independent promotion from c&d? Are all
> > integral promotions in the whole expression finished before any
> > further conversions (based on arirthmetic rules)?

I got lost here, but I think he means UACs at this point.

> Effectively, yes. Though an implementation can achieve this in
> various ways behind the scenes. [For instance, for the above
> expression, a given compiler may silently convert all the arguments
> to long before performing any arithmetic operation, if it can
> determine that this act won't change a required result.]

I haven't considered exactly the expression, but the answer in genaral
seems to me "No":
unsigned u1, u2;
unsigned long ul;
u1 + u2 + ul;
First u1 and u2 are added. If the result may overflow in unsigned type.
Then the result is converted to unsigned long and ul is added. If all
operands were converted at the start before arithmetic operations
the resulting value might be different.

--
Stan Tobias
mailx `echo (E-Mail Removed)LID | sed s/[[:upper:]]//g`

kiru.sengal@gmail.com
Guest
Posts: n/a

 01-29-2005

>
> > Integral Promotion
> > ===================
> > All chars and shorts are promoted to int(signed) before any

operating
> > is done on them.

>
> All short types, to signed or unsigned int, and only in certain

cases,
> not everywhere.

It's ridiculous how integral promotions done. The promotions vary
system to system. To me a "rule" like this shouldn't have an IF
STATEMENT attached to it (IF it fits, plug it into a signed int,
otherwise stuff it into an unsigned int), thus we have to live with the
confusions of both experts and beginners. Being someone who works with
8bit, 16bit, 32bit and 64bit micros, this really irritates me - only
way to write portable code is with extra-cautious casting or
preprocessor tricks.

Luke Wu
Guest
Posts: n/a

 01-29-2005

TTroy wrote:
> Hello, I'm relatively new to C and have gone through more than 4

books
> on it. None mentioned anything about integral promotion, arithmetic
> conversion, value preserving and unsigned preserving. And K&R2
> mentions "signed extension" everywhere.
>
> Reading some old clc posts, I've beginning to realize that these

books
> are over-generalizing the topic. I am just wondering what the
> difference between the following pairs of terms are:
>
> 1) Integral promotion vs. Arithmetic Conversion
> 2) Value Preserving vs. Unsigned Preserving
>
> I've read many, many old posts from c.l.c that referred to those 4
> terms constantly.. this is what I think they mean:
>
> Integral Promotion
> ===================
> All chars and shorts are promoted to int(signed) before any operating
> is done on them. If an unsigned short has the same bit-size as int,
> then the promotion is to unsigned int.
>
> Integral promotion is done as an intermediate step for all common
> computations.

Integral Promotion is not a "first pass" that is done on operands
before arithmetic conversions. Instead, it's a part of arithmetic
conversions (one of the steps).

Arithmetic Conversion (C89/90) follows like this:

1. If either operand is long double, the other is converted to long
double.
2. Otherwise, if either operand is double, the other is converted to
double.
3. Otherwise, if either operand is float, the other is converted to
float.
4. Otherwise, the integral promotions are performed on both operands;
then if either operand is unsigned long int, the other is converted to
unsigned long int.
5. Otherwise, if one operand is long int and the other is unsigned int,
the effect depends on whether a long int can represent all values of an
unsigned int; if so, the unsigned int operant is converted to long int;
if not, both are converted to unsigned long int.
6. Otherwise, if one operand is long int, the other is converted to
long int.
7. Otherwise, if either operand is unsigned int, the other is converted
to unsigned int.
8. Otherwise, both operands have type int.

If you look at step #4 in arithmetic conversions, you will find actions
pertaining to integral promotions. So Integral promotions only occur
if none of the other operands are of a floating point type (float,
double, long double). If the other operand is of a floating point
type, there is no integral promotion. If the other operand is not of a
floating point type, then all operands are first converted to a
minimum of (signed int or unsigned in), then the rest of the integer
related arithmetic conversions are done.

So, INTEGER PROMOTIONS are ONE STEP in ARITHMETIC PROMOTIONS (and if
there are floating point types involved, they aren't even the first
step).

>
> Ex:
>
> char a = 9;
> unsigned b = 4;
>
> a = b + a; /* a and b both converted to int before addition */
> /* the result is then converted back to char by the assignment */
>
> So basically, integral promotion gurantees that all intermediate
> computations are dealt with nothing "lower" than an int. Am I right?
>

Assignments obey different rules (neither Arithmetic Conversions or
Integer Promotions apply).

in a statement like: a = b;
All that happens is b is coerced to a's type, doesn't matter who has a
higher rank or whether or no b is at least an int.

Luke Wu
Guest
Posts: n/a

 01-30-2005

Peter Nilsson wrote:
>
> Kobu Selva wrote:
> >
> >
> > unsigned short a = -1;
> > signed short b = 45;
> > signed char c = -34;
> > unsigned char d = 21;
> > signed long f = LONG_MAX;
> > int = e;
> >
> > e = (a*b + c*d) * f;
> >
> > Are all a,b,c,d considered against the intergral promotion rule at
> > once?

>
> Yes.
>

No, not yes. All of them are not considered at once. First of all,
integral promotion is not an independent consideration, it's part of
the greater Usual Arithmetic Conversions (which includes floating
conversion, integral promotion, integer conversions - in that order).

The compiler will effectively look at the e = (a*b + c*d) * f
expression in steps, as can be explained by this parse tree:

.. =
.. / \
.. e *
.. / \
.. f +
.. / \
.. * *
.. / \ / \
.. a b c d

As you can see, at any instant, the compiler is dealing with only 1
operator and 2 operands. This smallest sub-expression is what the
compiler performs UAC on (following the steps I outlined in the
previous post). So let's say our system has the following
characteristic: USHRT_MAX > INT_MAX (unsigned short's range can't fit
in a signed integer).
Also assume that a & d are characters, b is a signed short and d is an
unsigned short.

So the compiler will consider each smalled sub expression
independently... so let's say the compiler deals with the a * b
subexpression first, since there are no floating point types, the first
step of UAC that applies to a * b is integral promotions. Since the
types of both a & b can fit in a signed int, they are promoted to a
signed int (which will be the result of the a * b sub expression). At
that point, no further steps of UAC apply, we're done for now.

Then let's say the compiler looks at c * d (it could have done this
before looking at a * b), the first step of UAC that applies to c * d
is integral promotions, since d is an unsigned short and USHRT_MAX >
INT_MAX, both c & d are converted to unsigned int, and that is the type
of the result. At that point, no futher steps of UAC apply, we're done
for now.

The next step would be to consider the sub expression held together by
the + in the tree (addition of the two results we've figured out from
now). Thus, we have the addition of a signed int and an unsigned int.
The first step of UAC that applies to this sub-expression is the
converstion of the signed int to the unsigned int, which will be the
type of the result.

Then we (or compiler) consider the top-most * in the tree, which
multiplies our result from just above with f. The first part of UAC
that applies here is the convesion of our result from above (unsigned
int) to float, which will be the type of our result. At that point, no
further steps of UAC apply (don't even have to consider integral
promotion).

So this is how we proceed up the tree, only looking at each smallest
sub expression (2 operands and 1 operator) when considering UAC. When
we reach the = operationg, UAC has no effect on it and conversion of
the right side's operands is made to match the type of the left operand
(e).

So this is how Integral Promotions, UAC, etc. apply to large
expressions. Compiler doesn't necessarily have to do everything
exactly like this. It can do it any way it wants, but it has to match
the behaviour we get from analysing expressions like this. You can't
look at a large expression and just say "all the chars, shorts,
bit-fields will be converted to ______ int" (where ______ is signed or
unsigned). Some could be converted in intermediate steps to unsigned
int, some could be converted in intermediate steps to signed int. They
are taken into consideration in pairs, and integral promotion is only
one consideration amongt many that make up UAC (if one of the operands
in a smallest sub-expression is a floating point type, integral
promotion will play no part with either operand).

TTroy
Guest
Posts: n/a

 01-30-2005

Luke Wu wrote:
> Peter Nilsson wrote:
> >
> > Kobu Selva wrote:
> > >
> > >
> > > unsigned short a = -1;
> > > signed short b = 45;
> > > signed char c = -34;
> > > unsigned char d = 21;
> > > signed long f = LONG_MAX;
> > > int = e;
> > >
> > > e = (a*b + c*d) * f;
> > >
> > > Are all a,b,c,d considered against the intergral promotion rule

at
> > > once?

> >
> > Yes.
> >

>
> No, not yes. All of them are not considered at once. First of all,
> integral promotion is not an independent consideration, it's part of
> the greater Usual Arithmetic Conversions (which includes floating
> conversion, integral promotion, integer conversions - in that order).
>
> The compiler will effectively look at the e = (a*b + c*d) * f
> expression in steps, as can be explained by this parse tree:
>
> . =
> . / \
> . e *
> . / \
> . f +
> . / \
> . * *
> . / \ / \
> . a b c d
>
> As you can see, at any instant, the compiler is dealing with only 1
> operator and 2 operands. This smallest sub-expression is what the
> compiler performs UAC on (following the steps I outlined in the
> previous post). So let's say our system has the following
> characteristic: USHRT_MAX > INT_MAX (unsigned short's range can't fit
> in a signed integer).
> Also assume that a & d are characters, b is a signed short and d is

an
> unsigned short.
>
> So the compiler will consider each smalled sub expression
> independently... so let's say the compiler deals with the a * b
> subexpression first, since there are no floating point types, the

first
> step of UAC that applies to a * b is integral promotions. Since the
> types of both a & b can fit in a signed int, they are promoted to a
> signed int (which will be the result of the a * b sub expression). At
> that point, no further steps of UAC apply, we're done for now.
>
> Then let's say the compiler looks at c * d (it could have done this
> before looking at a * b), the first step of UAC that applies to c * d
> is integral promotions, since d is an unsigned short and USHRT_MAX >
> INT_MAX, both c & d are converted to unsigned int, and that is the

type
> of the result. At that point, no futher steps of UAC apply, we're

done
> for now.
>
> The next step would be to consider the sub expression held together

by
> the + in the tree (addition of the two results we've figured out

from
> now). Thus, we have the addition of a signed int and an unsigned

int.
> The first step of UAC that applies to this sub-expression is the
> converstion of the signed int to the unsigned int, which will be the
> type of the result.
>
> Then we (or compiler) consider the top-most * in the tree, which
> multiplies our result from just above with f. The first part of UAC
> that applies here is the convesion of our result from above (unsigned
> int) to float, which will be the type of our result. At that point,

no
> further steps of UAC apply (don't even have to consider integral
> promotion).
>
> So this is how we proceed up the tree, only looking at each smallest
> sub expression (2 operands and 1 operator) when considering UAC.

When
> we reach the = operationg, UAC has no effect on it and conversion of
> the right side's operands is made to match the type of the left

operand
> (e).
>
> So this is how Integral Promotions, UAC, etc. apply to large
> expressions. Compiler doesn't necessarily have to do everything
> exactly like this. It can do it any way it wants, but it has to

match
> the behaviour we get from analysing expressions like this. You can't
> look at a large expression and just say "all the chars, shorts,
> bit-fields will be converted to ______ int" (where ______ is signed

or
> unsigned). Some could be converted in intermediate steps to unsigned
> int, some could be converted in intermediate steps to signed int.

They
> are taken into consideration in pairs, and integral promotion is only
> one consideration amongt many that make up UAC (if one of the

operands
> in a smallest sub-expression is a floating point type, integral
> promotion will play no part with either operand).

If that is the case, I'm never using a short ever in my life. Why would
anyone use a short?????? Such variability and doubt for large
expressions (and the variability is multiplied along every step of the
computation)!!!!!