2
votes

This topic has been heavily discussed in many context. When I search and read some of posts. I was confused by following post.

Signed to unsigned conversion in C - is it always safe?

The following is the original question.

unsigned int u = 1234;
int i = -5678;
unsigned int result = u + i;

The answer simply quotes the "6.3.1.8 Usual arithmetic conversions" point 3, i.e.,

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

However, if my understanding is correct, the integer promotion should be done before considering "usual arithmetic conversions".

And the rules for that is

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 conversion rules are called the integral promotions

So, that means the addition is completed with type of signed int than unsigned int. And the conversion to a large value occurs when assigning an negative to unsigned int result.

I am a bit non-confident on my understanding. Does anyone have similar confusion on that post?

Any reply or comment is welcome. Thanks advance!

Jeff

3

3 Answers

3
votes
unsigned int result = u + i;

We have an additive operator. Additive operators with operands of arithmetic type perform usual arithmetic conversions first.

Usual arithmetic conversions are done in two steps:

First integer integer promotions are applied to each operand:

  • u is not promoted to int as it is unsigned int
  • i is already int, no need to promote it to int

As operands actually have a type rank equal to int, so no integer promotion is performed.

Second, bring operand to a common type. The common type is unsigned int.

  • u is already unsigned int
  • i is type int and is converted to unsigned int

After the usual arithmetic conversions the two values of type unsigned int are added and the result assigned to result.

2
votes

However, if my understanding is correct, the integer promotion should be done before considering "usual arithmetic conversions".

Correct, but integer promotion, as defined by the integer promotion rule, only applies to small integer types, such as char and short. You only cited half of the paragraph, which might have made you confused. Let me cite that paragraph as whole:

C11 6.3.1.1/2

The following may be used in an expression wherever an int or unsigned int may be used:

  • An object or expression with an integer type (other than int or unsigned int) whose integer conversion rank is less than or equal to the rank of int and unsigned int.

  • A bit-field of type _Bool, int, signed int, or unsigned int.

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.

So integer promotion do not apply to int or unsigned int, because they do not have lesser conversion rank.

So, that means the addition is completed with type of signed int than unsigned int. And the conversion to a large value occurs when assigning an negative to unsigned int result.

Incorrect, the addition is done on usigned int, because of the usual arithmetic conversions.

0
votes

I will use hexadecimal representation in order to explain the issue...

Assuming that the size of an int variable is 32 bits:

  • +1234 = 0x000004D2
  • -5678 = 0xFFFFE9D2

When doing a+b, it doesn't matter how each one of them is represented (signed or unsigned). If you add the two values above and store the result in an int variable, then it will hold a value of 0xFFFFEEA4, regardless of the sign of each operand:

  • If the output variable is signed, then it will be treated (in other operations) as -4444.
  • If the output variable is unsigned, then it will be treated (in other operations) as 4294962852.