izac89
izac89

Reputation: 3940

Trying to understand signed integer conversion rule from the standard

Trying to understand the syntax in the standard:

6.3.1.3 Signed and unsigned integers

  1. When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
  2. Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
  3. Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

Note section 2, which means that casting int to unsigned int is performed by adding UINT_MAX + 1 to the value in the int.

Which is discussed for example in those two discussions:

Can a C compiler change bit representation when casting signed to unsigned?

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

Well, since UINT_MAX + 1 is always promised to be zero (https://stackoverflow.com/a/14899158/2162550) section 2 can be read as:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting zero until the value is in the range of the new type.

Which makes no sense to me, since adding zero change nothing. Is my english interpretation is broken? What am I missing here?

Upvotes: 3

Views: 297

Answers (2)

Firstly, there are two important words missing from the C standard excerpt that need to be read into it

  • Otherwise, if the new type is unsigned, the value is converted [as if] by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

I.e. the whole bullet point talks about how the abstract machine would do calculations. In actuality no system would use repeated additions / subtractions to reduce the value into the range.

The one more part can only be understood to mean a value that is not representable in the unsigned type, otherwise it wouldn't be one more, i.e. >. The wording can be contrasted with + 1 which is ambiguous.

Another way of expressing the conversion is that the result is the positive remainder of the division of the result by one more than the maximum representable value.

Upvotes: 2

Keith Thompson
Keith Thompson

Reputation: 263647

  1. Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

In this context, "adding or subtracting" refers to operating on the mathematical value, not on the C value using C's + and - operators.

For example, if the starting value is -42 and UINT_MAX is 65535, then the result is -42 + 65536, or 65494. This mathematical value is within the range of unsigned int, yielding a C value of 65494U.

It's true that the result of evaluating the C expression UINT_MAX + 1 is zero. That's why the standard refers to "one more than the maximum value that can be represented in the new type" rather than UINT_MAX + 1. (Admittedly it could be stated a bit more clearly.)

Upvotes: 7

Related Questions