33

This question is asked before but I am still confused.

I know that

unsigned int a = -1;

would be UINT_MAX. But it is not because all bits of -1 is set. C11 says

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

So lets say UINT_MAX is 100 (I know it should be greater then 2^16-1 but lets ignore this for now)

unsigned int a = -1; // will be
unsigned int a = -1 + UINT_MAX + 1; // 100 = UINT_MAX  

Standard only says UINT_MAX >= 2^16-1. But does it say anywhere it should be 2^n-1?

Also is answer different in C++?

MrDarkLynx
  • 686
  • 1
  • 9
  • 15
  • 6
    I think that the standard mostly leaves the exact bit representation of values unspecified (or platform dependent). There are (have been) some really strange architectures out there. – Richard Critten Feb 17 '17 at 12:04

3 Answers3

46

In C, the maximum value for an unsigned integer must be in the form1: 2N - 1.

Thus all value bits of the value UINT_MAX will be set to 1. There may be padding bits, whose values are unspecified.


1 (Quoted from: ISO/IEC 9899:201x 6.2.6.2 Integer types 1)
For unsigned integer types other than unsigned char, the bits of the object representation shall be divided into two groups: value bits and padding bits (there need not be any of the latter). If there are N value bits, each bit shall represent a different power of 2 between 1 and 2N−1 , so that objects of that type shall be capable of representing values from 0 to 2N−1 using a pure binary representation; this shall be known as the value representation. The values of any padding bits are unspecified.

2501
  • 25,460
  • 4
  • 47
  • 87
11

No, not quite.

An unsigned type can consist of value bits and padding bits.

You are correct that the value bits will always be set to 1 for the maximum value, but the specific values of the padding bits is left to the implementation. So this means that UINT_MAX needs to be a Mersenne number. Other requirements state it can't be less than 65535.

C and C++ are equivalent in this respect.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • But that still requires UINT_MAX must be of the form 2^n - 1, for some n >= 16. – Martin Bonner supports Monica Feb 17 '17 at 12:17
  • Indeed it does: i.e. a Mersenne number (not necessarily prime), greater than or equal to 65535. – Bathsheba Feb 17 '17 at 12:17
  • I can't find anything in the C++14 standard about fundamental types having any padding bits. The only think I can see referencing the C standard in `[basic.fundamental]` is it must respect C 5.2.4.2.1 which is the limits sections. – NathanOliver Feb 17 '17 at 12:48
  • 4
    Minor nitpick: It may be good to clarify the reference to the Mersenne numbers as [the term is usually reserved for 2^p-1](https://oeis.org/A000225) with *p* prime. Though *p* is often generalised, with abuse of notation, to every positive integer. – Margaret Bloom Feb 17 '17 at 17:58
2

You're correct to say that by the definition of conversions, -1 converted to unsigned int is guaranteed to be UINT_MAX. It hasn't anything to do with any bit patterns. If there was an implementation where UINT_MAX was 100, then -1 converted to unsigned int would be 100.

There are reasons why UINT_MAX cannot be 100: One because it must be ≥ 2^16-1, but that would allow UINT_MAX = 1,000,000. Second, because unsigned int must have a binary representation with some fixed number n of value bits, so UINT_MAX = 2^n - 1.

It is possible that INT_MAX = 2^31 - 1 and UINT_MAX = 2^31 - 1 (not 2^32 - 1 as it is usually). In that case -1 would have 32 bits set; -1 cast to unsigned int would be 2^31 - 1 and have only 31 bits set.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • Tiny nitpick: -1 in 1+31-bit `signed int` has 32 bits set _if implementation uses two's complement_, which practically all machines since the mid-'80s do for integers, but 6.2.6.2p2 _allows_ ones' complement or sign and magnitude which would have 31 bits and 2 bits respectively. – dave_thompson_085 Feb 17 '17 at 16:46
  • @dave_thompson_085: A system with 32-bit two's-complement signed integer would almost certainly have a 32-bit unsigned integer as well. Just about the only reason that a non-contrived implementation would have an `unsigned` type with fewer possible values than the corresponding signed type would be that hardware was limited to a form of signed arithmetic which couldn't accommodate 2ⁿ distinct values. – supercat Feb 17 '17 at 19:33