2

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

Community
  • 1
  • 1
Poor
  • 51
  • 5

3 Answers3

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

ouah
  • 142,963
  • 15
  • 272
  • 331
  • It seems that I have a bit misunderstanding on the second rule in above post. My understanding is int can represent the value of u, so, u should be promoted to int, than *unsigned int*. Is it wrong? – Poor Feb 12 '14 at 10:54
  • @Poor the first step are the integer promotions, and here the promoted operands are of the same type before and after the promotion. In the second step, C says (in c99, 6.3.1.8p1) *"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."* And the conversion rank of types `unsigned int` and `int` is the same. That's the reason why `i` is converted to `unsigned int` in the second step. – ouah Feb 12 '14 at 11:01
  • "As operands actually have a type rank less than.." you probably meant "As both operands actually have a type rank equal to..."? – Lundin Feb 12 '14 at 12:17
2

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • +1 Removed my answer as it answered only half of the question. This answer has it all. – user694733 Feb 12 '14 at 11:30
  • @Lundin You are correct, I overlook the condition for integer promotion or didn't fully understand what that condition mean. The trap statement is *(other than int or unsigned int)*. – Poor Feb 12 '14 at 14:47
0

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.
barak manos
  • 29,648
  • 10
  • 62
  • 114