11

Is for example

size_t x = -1u;

if (x == -1u)
    ...

valid?

If this is valid it would prevent a warning. of course on a 32 bit system x should be 0xffffffff and on a 64 bit system it should be 0xffffffffffffffff.

-Jochen

OmarOthman
  • 1,588
  • 2
  • 17
  • 35
Jochen
  • 716
  • 5
  • 21
  • 7
    Literals are always non-negative. This is parsed as `-(1u)`. – Kerrek SB Dec 05 '11 at 20:55
  • @KerrekSB does that make a difference here? – Seth Carnegie Dec 05 '11 at 20:58
  • Well, it makes the result signed, so it kind of defeats the purpose of the U. – StilesCrisis Dec 05 '11 at 21:01
  • `-1u` probably *won't* be `2^64 - 1` on a 64 bit system. `-1UL` *might* be - but not on Windows. `-1ULL` almost certainly will be. – Brett Hale Dec 05 '11 at 21:01
  • "If this is valid it would prevent a warning." It would help to get to the bottom of your question if you said what other form you tried to use and what the warning was. For instance, if your compiler warns on `size_t x = -1;`, which is defined although it may indicate a programmer mistake, I do not see why it wouldn't warn on `size_t x = -1u;` which is defined although it may indicate a programmer mistake. – Pascal Cuoq Dec 05 '11 at 21:01
  • 4
    If your goal is to get `0xFFFFFFFF` on a 32-bit system and `0xFFFFFFFFFFFFFFFF` on a 64-bit system, wouldn't it be clearer to write `size_t x = ~0U`? – ruakh Dec 05 '11 at 21:02
  • 2
    ~0U is all bits on, -1U is highest number possible. – Pubby Dec 05 '11 at 21:04
  • 3
    @ruakh ... although that does not solve the issue where `size_t` is wider than `unsigned int`, which may be what the OP had in mind. The expression `~0U` evaluates to the same value as `UINT_MAX`. – Pascal Cuoq Dec 05 '11 at 21:06
  • 1
    @Complicatedseebio: Good point; I suppose it would have to be `~((size_t)0U)`. Or just `SIZE_MAX`, assuming C99. – ruakh Dec 05 '11 at 21:13
  • Are you merely trying to set all bits, or get the largest number a platform specific `size_t` will hold? Is there a reason you're not using the built-in compiler constants (ie, you need portable code)? – Adam Davis Dec 05 '11 at 22:05

5 Answers5

7

1u has the type unsigned int. This is then negated using the unary - operator. The behavior is as follows:

The negative of an unsigned quantity is computed by subtracting its value from 2n, where n is the number of bits in the promoted operand (C++11 5.3.1/8).

-1u is thus guaranteed to give you the largest value representable by unsigned int.

To get the largest value representable by an arbitrary unsigned type, you can cast -1 to that type. For example, for std::size_t, consider static_cast<std::size_t>(-1).

James McNellis
  • 327,682
  • 71
  • 882
  • 954
5

I've always used ~0U for the purpose of "unsigned, all bits on".

StilesCrisis
  • 15,362
  • 4
  • 33
  • 58
  • 1
    SIZE_MAX is probably better in that case, or ~0ULL as a fallback. – StilesCrisis Dec 05 '11 at 21:55
  • However take care not to write `~0`. The `U` in here is very important. For further discussion, see http://stackoverflow.com/questions/809227/is-it-safe-to-use-1-to-set-all-bits-to-true – Johannes Schaub - litb Dec 05 '11 at 22:57
  • What, because we're worried about one's-complement hardware coming back? I think that ship has sailed :) I mean, sure, the U is more correct, but I expect you'd see a LOT more problems than that if you tried to port a typical app to a one's-complement architecture. – StilesCrisis Dec 05 '11 at 23:30
  • 1
    @StilesCrisis: One's complement is not coming back but systems that assert on overflow are still with us. – Joshua Dec 06 '11 at 03:08
1

Compiler implementation dependant behavior is annoying. You should be able to do this, though:

size_t x = 0;
x--;

if ((x+1) == 0)
Pubby
  • 48,511
  • 12
  • 121
  • 172
Adam Davis
  • 87,598
  • 55
  • 254
  • 328
  • @Pubby: What in this answer do you think exhibits undefined behavior? – James McNellis Dec 05 '11 at 21:25
  • 1
    Pubby where do you see UB? Unsigned types (and size_t is an unsigned types) have well defined behavior on overflow, they wrap around. (Signed overflow is UB). – AProgrammer Dec 05 '11 at 21:25
  • @AProgrammer Is that so? I'll gladly remove the downvote if point me to a reference. – Pubby Dec 05 '11 at 21:29
  • 3
    @Pubby, "Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer." 3.9.1/4 in C++-03 – AProgrammer Dec 06 '11 at 10:45
  • 1
    @AProgrammer Thanks! Apologies for my mistake. – Pubby Dec 06 '11 at 10:54
0

While this is technically valid code, you are depending on implementation dependent behavior: overflow handling of converting a negative number to unsigned. However, if you need to meaningful compare a size_t with -1 because the API calls you are using require it, the system is already screwed up but your code is likely to work because they would have had to do the same thing on the other side of the API.

Joshua
  • 34,237
  • 6
  • 59
  • 120
  • I am not a C++ expert but I doubt converting from signed integer type to unsigned integer type is implementation-defined in C++, because it's defined in C99. – Pascal Cuoq Dec 05 '11 at 21:08
  • It's well defined. I think it's something like `x % 2^32` for 32 bits. – Pubby Dec 05 '11 at 21:10
  • 1
    No negative number is converted to unsigned. `1u` is a positive number of type `unsigned int`, and that positive number is negated using the unary `-` operator. – James McNellis Dec 05 '11 at 21:19
  • size_t is almost always unsigned. – Joshua Dec 05 '11 at 22:27
0

This is likely what you want:

size_t x = -1ull;

if (x == -((size_t)-1ull))
    ...

x will be set to the largest integer possible, which may not be all bits set. Use ~0 for that.

Pubby
  • 48,511
  • 12
  • 121
  • 172
  • Many years from now when `size_t` is wider than `unsigned long long`, `size_t x = -1ull;` (perhaps `size_t` as a typedef to a wide `uintmax_t`) will fail to be initialed `x` with the max value. `size_t x = SIZE_MAX;` will still work. – chux - Reinstate Monica Dec 07 '17 at 16:27