I'm learning C++ coming from doing JavaScript professionally for years. I know the differences between signed
and unsigned
, but I'm not sure I understand why they even exist. Is it for performance or something?

- 854,327
- 234
- 1,573
- 1,953

- 31,662
- 41
- 121
- 201
-
1Expressiveness perhaps? You could turn it around and ask why other languages *don't* have unsigned types. The size of an array is certainly something that's naturally unsigned... – Kerrek SB Jan 25 '13 at 22:53
-
Some variables that are integers would be meaningless if they could be negative, like array indices. It gives you more meaning and more range simultaneously. – Seth Carnegie Jan 25 '13 at 22:53
-
@SethCarnegie: And yet, in many languages (including C#), the default is to use a signed number for such indexes. – Robert Harvey Jan 25 '13 at 22:54
-
1@RobertHarvey a design flaw. – Seth Carnegie Jan 25 '13 at 22:54
-
1Not if you need the number to be negative to signal out-of-range. – Robert Harvey Jan 25 '13 at 22:54
-
There is time for bit twiddling and time for math. It makes sense to make both things equally easy for any word size. – Anton Kovalenko Jan 25 '13 at 22:55
-
@SethCarnegie Not necessarily. When an array index overflows, a negative index will be an easy to detect exception condition for the framework. But when it's signed and the array is as large as the range of the integer, an integer overflow will still result in valid values, which makes the bug hard to detect. – Philipp Jan 25 '13 at 22:55
-
1@SethCarnegie In C, how would you reference the previous character in a string using a pointer that points to the middle of that string? `p[-1]`, of course... – Jan 25 '13 at 22:56
-
@RobertHarvey that should be an exception. Philipp signed integer overflow is UB in C++. H2C03 yeah, but `p` is a pointer, not an array, I said array indices. But that's just an example, other things can't be negative, like the size of an array or something. – Seth Carnegie Jan 25 '13 at 22:59
-
@SethCarnegie But not in C#. Overflow checking has to be enabled with the `checked {` block. When you forget to do that, integers overflow. – Philipp Jan 25 '13 at 23:07
-
@Philipp you can still detect overflow with unsigned numbers, and that'd give you more range so an overflow would be twice as hard to do :) – Seth Carnegie Jan 25 '13 at 23:08
-
@SethCarnegie sure you can, but it's easy to forget to do it. One design goal of languages like C# is to protect the programmer from stupid mistakes. – Philipp Jan 25 '13 at 23:11
-
Do we really need 2 billion different values for 'out of range error'? – JasonD Jan 25 '13 at 23:14
-
@Philipp you can overflow a signed integer back to being positive too, so that's not a good reason. – Seth Carnegie Jan 25 '13 at 23:15
-
@JasonD: Erm, it's *one bit.* – Robert Harvey Jan 25 '13 at 23:42
-
@RobertHarvey yes, exactly. 1 bit = half the available range. – JasonD Jan 25 '13 at 23:48
-
@RobertHarvey the most significant bit. – Seth Carnegie Jan 25 '13 at 23:48
-
@JasonD: I can't remember the last time I needed four-billion elements in an array instead of two-billion. – Robert Harvey Jan 25 '13 at 23:49
-
I'm more likely to need >2 billion elements in an array than I am to need 2 billion different error codes. – JasonD Jan 25 '13 at 23:52
-
In the early days of C this mattered a great deal. No 32-bit machines back then. – Hans Passant Jan 26 '13 at 02:07
5 Answers
Because they're needed.
signed
types exist because sometimes one wants to use negative numbers.
unsigned
types exist because for some operations, e. g. bitwise logic and shifting, they're cleaner to use (e. g. you don't have to worry about how the sign bit is represented, etc.)
-
Yeah, but why doesn't it handle a negative number just like any other int? That's where I was confused. Your unsigned explanation makes sense for low-level operations and thats where I'm thinking this is actually really important. – Oscar Godson Jan 25 '13 at 23:00
-
@OscarGodson What do you mean by 'it doesn't handle a negative number just like any other int'? It does. – Jan 25 '13 at 23:02
-
@OscarGodson two's complement representation for negatives is just an "implementation detail", i.e. you don't even know that value `-1` has all bits set. Given that, it's impossible to allow negative numbers with known and useful representation. (common lisp standard went the other way, they required "as if" rule for two's complement). – Anton Kovalenko Jan 25 '13 at 23:06
-
@OscarGodson: Please read [Integer overflow and undefined behavior](http://stackoverflow.com/questions/3948479/integer-overflow-and-undefined-behavior). Historically, it was because not all CPU architectures did wraparound, however, nowadays it has to do with optimization. – Jesse Good Jan 26 '13 at 21:30
You can argue that with unsigned values you can obtain a larger positive range than with the equivalent signed types, but the main reason is that they allow mapping concepts in the domain where negative numbers make little or no sense. For example, the size of a container can never be negative. By using an unsigned type that becomes explicit in the type.
Then again, the existence of the two, and the implicit conversions pull a whole different set of problems...

- 204,818
- 23
- 294
- 489
It comes in handy for low level situations where you need to describe length which obviously can't be negative. File sizes for example.

- 34,865
- 12
- 85
- 147
They exist because the math to handle can differ.
Consider multiplying two 32 bit values to get a 64 bit value. Depending upon the sign of the operands, the upper 32 bits can differ between a signed multiply and an unsigned multiply. Getting down to assembly, this is why there is an IMUL and MUL instructions on the x86.

- 13,505
- 4
- 26
- 27
C is designed to be a high-level language but also able to do low-level stuffs easily, such as directly inserting assembly language code into the source code using the _ASM keyword. Assembly language works directly with the CPU registers and the arithmetic instructions work with both signed and unsigned integer. The variable type are probably designed in such way so that values can be transfer between CPU registers and variables without any conversion at all. C++ which extended from C also inherit this feature. After all, at that time when the C/C++ is invented, most of the programmers are also hardware engineers too.

- 565
- 2
- 6