2

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?

izac89
  • 3,790
  • 7
  • 30
  • 46
  • 2
    See https://en.wikipedia.org/wiki/Modular_arithmetic . The bold text refers to mathematical operations on the integers, not C expressions on typed C values – M.M Jul 11 '19 at 05:28
  • @M.M you mean that the text means `int_var + UINT_MAX + 1` which means first performing `int_var + UINT_MAX` and only than adding `1` ? – izac89 Jul 11 '19 at 05:33
  • No, I mean what I said – M.M Jul 11 '19 at 05:36
  • @M.M can you elaborate more? clearly I need more help understanding that – izac89 Jul 11 '19 at 05:37
  • The wiki link elaborates more, I'm not sure what else to say – M.M Jul 11 '19 at 05:38
  • @M.M the wiki simply says that `UINT_MAX + 1` is wrapped to zero, which is the root of my question, as `0` changes nothing when adding\subtracting it – izac89 Jul 11 '19 at 05:39
  • 4
    *adding or subtracting one more than the maximum value that can be represented in the new type* is a description of a mathematical expression, not of a C expression. – n. m. could be an AI Jul 11 '19 at 05:41
  • Mathematically, UINT_MAX + 1 and 0 are different numbers but they are congruent modulo UINT_MAX + 1 . In C the result of the operation is the member of that congruence class which falls within the range of values representable by the type – M.M Jul 11 '19 at 05:43
  • I think I understand what you talking about, I think it's equivalent to C expression of first `int_var + UINT_MAX` which will wrap to some value, than adding `1`, which will explain my conversion rule misunderstanding. isn't it? anyway if you could compose an answer I'll accept it – izac89 Jul 11 '19 at 05:43
  • Modular addition is associative, (a + b) + 1 (mod c) gives the same result as a + (b + 1) (mod c) – M.M Jul 11 '19 at 05:45
  • The C expression `int_var + UINT_MAX` is not equivalent to anything in this paragraph. – n. m. could be an AI Jul 11 '19 at 05:50
  • Imagine you're doing this on a calculator with infinite precision , not in C variables – M.M Jul 11 '19 at 05:51

2 Answers2

6
  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.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
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.