So I understand that unsigned
variables can only hold positive values and signed
variables can hold negative and positive. However, it is unclear to me why would someone use unsigned
variables? Isn't that risky? I mean I would personally just stick with signed
variables just in case. Is there a memory/performance advantage in using unsigned
variables?

- 113
- 1
- 9
-
Signed integers are also risky (see UB), so where does that leave us – harold Aug 06 '16 at 19:41
-
Apart from more complex reasons (UB with signed integers), one very obvious reason is that you need that extra range that unsigned integers give you. – Banex Aug 06 '16 at 19:43
-
1@harold sometimes UB helps optimization. I had to investigate case when switching to size_t caused perfomance degradation because compiler couldn't optimize away huge loop. – Revolver_Ocelot Aug 06 '16 at 19:49
3 Answers
Selecting the right kind of primitive data type for your particular problem is all about being correct about showing your intent. While, for example, a size of an array might as well be stored in a signed type (like it is the case in Java or C#), but why should you? An array cannot be of negative size. Doing so anyway is only confusing to readers of your program and will not give you any benefit.
There is no measurable performance gain by not using unsigned values; actually it can even be dangerous to do so since unsigned values can hold bigger positive numbers than signed values of the same memory size, thus risking a narrowing conversion when assigning, for example, array sizes that are naturally unsigned to a signed value of same memory size:
// While unlikely, truncation can happen
int64_t x = sizeof(...);
// ~~~~^~~~~~~ uint64_t on my system
Those bugs are generally hard to track, but compilers have gotten better at warning you about committing them.
Naturally, you should be aware that using unsigned integers can indeed be dangerous in some cases. As an example I wrote a simple for
loop. We do not expect the value i
to be negative, so we do the seemingly correct decision to use a value of unsigned type:
for(unsigned i = 5; i >= 0; --i)
{
}
But in this case, the loop will never terminate since the unsigned value of 0 - 1
(happens in fifth iteration here) will be a big positive value (this is called wrap around), thus defeating the loop termination check.
This can, for example, be solved like this:
for(unsigned i = 5; (i+1) > 0; --i)
{
}
But this should not deter you from using the right data type. Just exercise caution about things like value ranges and wrap around and you will be fine.
In conclusion, use the type that is most appropriate and seems to show your intent the best.

- 5,716
- 8
- 28
- 43

- 1,197
- 9
- 29
-
1
-
also, unsigned & signed types are distinct in the language because they are distinct in the hardware and the language is designed to map the hardware. – 1stCLord Aug 06 '16 at 19:57
-
Sure. But the example was meant to show an example of something a lot of new programmers do wrong. – nshct Aug 06 '16 at 19:57
-
@EmilioGaravaglia Or as `i <= 5`. The main issue is just that it's something people don't usually think about doing. – Justin Time - Reinstate Monica Aug 06 '16 at 20:02
-
-
@JustinTime ah ah ... yeah ! A bit more difficult to grasp... – Emilio Garavaglia Aug 06 '16 at 20:04
-
@alain Good point. I guess it would depend on where the loop is used. – Justin Time - Reinstate Monica Aug 06 '16 at 20:06
Unsigned is more appropriate if your value is actually a bit-field, and if you do bit manipulations.
Signed behaviour is by default undefined if an operation causes an overflow.

- 9,064
- 3
- 31
- 49
-
-
1@Rakete1111 it probably should be _"by standard"_. I know large codebases which use `-fwrapv` – Revolver_Ocelot Aug 06 '16 at 19:47
-
The ranges of signed and unsigned numbers are different.
For example, on a 32 bit system the range of a signed integer would be between -2G and 2G - 1 (i.e. -2147483648 to 2147483647).

- 7,378
- 5
- 31
- 40