Velocity Reviews > C++ > Arithmetic/Comparison between different integer types

Arithmetic/Comparison between different integer types

Frederick Gotham
Guest
Posts: n/a

 07-07-2006

I just want to clarify my understanding of arithmetic and comparison
between two different integer types.

Phase (1): Integer Promotion
----------

All of the following types always get promoted to "signed int":

signed char
signed short

All of the following types get promoted to "signed int" if it has
sufficient range on the platform; otherwise, they go to "unsigned int".

char
unsigned char
unsigned short

Phase (2): Now working with "int" and upwards
----------

Now everything is one of the following types:

signed int
unsigned int
signed long
unsigned long

That leaves us with 10 possibilities. The first four are straight-forward:

(1) signed int + signed int
(2) unsigned int + unsigned int
(3) signed long + signed long
(4) unsigned long + unsigned long

The following involve the same type, but different signedness. Am I right
in thinking that they both become "unsigned int" in (5), and both become
"unsigned long" in (6)?

(5) signed int + unsigned int
(6) signed long + unsigned long

Then there's two different types which have the same signedness. Would I be
right in thinking that they both become signed long in (7), and both become
unsigned long in (?

(7) signed int + signed long
( unsigned int + unsigned long

Now here's the dirty ones which I'm least sure about. What happens in (9)
and (10)? Are (9) and (10) implementation-specific depending on whether
numeric_limits<long>::digits > numeric_limits<int>::digits?

(9) signed int + unsigned long
(10) unsigned int + signed long

--

Frederick Gotham

Robbie Hatley
Guest
Posts: n/a

 07-07-2006

"Frederick Gotham" <(E-Mail Removed)> wrote:

> I just want to clarify my understanding of arithmetic and comparison
> between two different integer types.
>
>
> Phase (1): Integer Promotion
> ----------
>
> All of the following types always get promoted to "signed int":
>
> signed char
> signed short
>
> All of the following types get promoted to "signed int" if it has
> sufficient range on the platform; otherwise, they go to "unsigned int".
>
> char
> unsigned char
> unsigned short
>
> Phase (2): Now working with "int" and upwards
> ----------
>
> Now everything is one of the following types:
>
> signed int
> unsigned int
> signed long
> unsigned long
>
> That leaves us with 10 possibilities. The first four are straight-forward:
>
> (1) signed int + signed int
> (2) unsigned int + unsigned int
> (3) signed long + signed long
> (4) unsigned long + unsigned long
>
> The following involve the same type, but different signedness. Am I right
> in thinking that they both become "unsigned int" in (5), and both become
> "unsigned long" in (6)?
>
> (5) signed int + unsigned int
> (6) signed long + unsigned long
>
>
> Then there's two different types which have the same signedness. Would I be
> right in thinking that they both become signed long in (7), and both become
> unsigned long in (?
>
> (7) signed int + signed long
> ( unsigned int + unsigned long
>
> Now here's the dirty ones which I'm least sure about. What happens in (9)
> and (10)? Are (9) and (10) implementation-specific depending on whether
> numeric_limits<long>::digits > numeric_limits<int>::digits?
>
> (9) signed int + unsigned long
> (10) unsigned int + signed long

The C++ standard, section 5, paragraph 9 reads:

Many binary operators that expect operands of arithmetic or enumeration
type cause conversions and yield result types in a similar way. The purpose
is to yield a common type, which is also the type of the result. This
pattern is called the usual arithmetic conversions, which are defined as
follows:
— If either operand is of type long double, the other shall be converted
to long double.
— Otherwise, if either operand is double, the other shall be converted to
double.
— Otherwise, if either operand is float, the other shall be converted to
float.
— Otherwise, the integral promotions (4.5) shall be performed on both
operands.54)
— Then, if either operand is unsigned long the other shall be converted
to unsigned long.
— Otherwise, if one operand is a long int and the other unsigned int, then
if a long int can represent all the values of an unsigned int, the unsigned
int shall be converted to a long int; otherwise both operands shall be
converted to unsigned long int.
— Otherwise, if either operand is long, the other shall be converted to long.
— Otherwise, if either operand is unsigned, the other shall be converted to
unsigned.
[Note: otherwise, the only remaining case is that both operands are int ]

So most of your cases are set in concrete:
In your cases 1,2,3,4 no conversions would occur.
In your case 5, both operands would be converted to unsigned int
In your cases 6, 8, 9, both operands would be converted to unsigned long.
In your case 7, both operands would be converted to signed long

The only case that's implimentation dependent is your case 10.
If long can represent the values, both operands will be converted to long.
However, on most modern 32-bit PCs, long can NOT represent all the values
of unsigned int. Usually the ranges are:
long: -2147483648 to 2147483647
unsigned: 0 to 4294967296
On such machines, in your case 10, both operands will be converted to
unsigned long int, which is usually identical in range to unsigned int.
So any negative values will be converted to very large positive values.
Depending on the application, that could be a disaster or a don't-care.

--
Cheers,
Robbie Hatley
Tustin, CA, USA
lonewolfintj at pacbell dot net (put "[ciao]" in subject to bypass spam filter)
http://home.pacbell.net/earnur/

Frederick Gotham
Guest
Posts: n/a

 07-07-2006
Robbie Hatley posted:

<snip explanation>

Thank you, very helpful.

Now I think I'll go over my code looking for any potential booby traps.

--

Frederick Gotham