7

In C++ we can make primitives unsigned. But they are always positive. Is there also a way to make unsigned negative variables? I know the word unsigned means "without sign", so also not a minus (-) sign. But I think C++ must provide it.

CharlesB
  • 86,532
  • 28
  • 194
  • 218
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • "unsigned" in C/C++ is really a synonym for nonnegative. – President James K. Polk Jun 12 '10 at 16:59
  • 13
    Just assume they represent negative numbers. – Khaled Alshaya Jun 12 '10 at 17:01
  • 1
    Interesting question I have never heard asked before. Unfortunately, the answer is "no." – John Dibling Jun 12 '10 at 17:09
  • 5
    If you ignore overflow, signed integers and positive integers are both closed over the arithmetic operations. negative numbers are only closed over addition and subtraction - multiplication and division gives you a positive number. So your class will have to be a little strange, as half the basic set of operations return a different type to their arguments, unlike any other numeric type in C++. – Pete Kirkham Jun 12 '10 at 17:23
  • @Pete Kirkham: good point. Note that in C++, the various `unsigned` types have well defined overflow behavior (guaranteed modulo 2^N). Therefore, even when you don't ignore overflow, C++ unsigned integers are closed over addition, subtraction, multiplication and division (except of course for /0). – MSalters Jun 14 '10 at 12:20

5 Answers5

4

No. unsigned can only contain nonnegative numbers.

If you need a type that only represent negative numbers, you need to write a class yourself, or just interpret the value as negative in your program.

(But why do you need such a type?)

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
2

unsigned integers are only positive. From 3.9.1 paragraph 3 of the 2003 C++ standard:

The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type, and the value representation of each corresponding signed/unsigned type shall be the same.

The main purpose of the unsigned integer types is to support modulo arithmetic. From 3.9.1 paragraph 4:

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.

You are free, of course, to treat them as negative if you wish, you'll just have to keep track of that yourself somehow (perhaps with a Boolean flag).

Brian Neal
  • 31,821
  • 7
  • 55
  • 59
0

I think you are thinking it the wrong way.

If you want a negative number, then you must not declare the variable as unsigned.

If your problem is the value range, and you want that one more bit, then you could use a "bigger" data type (int 64 for example...).

Then if you are using legacy code, creating a new struct can solve your problem, but this is that way because of your specific situation, C++ shouldn't handle it.

Diego Pereyra
  • 417
  • 3
  • 10
0

Don't be fooled by the name: unsigned is often misunderstood as non-negative, but the rules for the language are different... probably a better name would have been "bitmask" or "modulo_integer".

If you think that unsigned is non-negative then for example implicit conversion rules are total nonsense (why a difference between two non-negative should be a non-negative ? why the addition of a non-negative and an integer should be non-negative ?).

It's very unfortunate that C++ standard library itself fell in that misunderstanding because for example vector.size() is unsigned (absurd if you mean it as the language itself does in terms of bitmask or modulo_integer). This choice for sizes has more to do with the old 16-bit times than with unsigned-ness and it was in my opinion a terrible choice that we're still paying as bugs.

6502
  • 112,025
  • 15
  • 165
  • 265
  • 2
    What benefit does making vector.size() signed give? It can never return a negative value. Exactly what bugs arise because of signed/unsigned? It's a pretty simple concept to deal with. – Puppy Jun 12 '10 at 20:24
  • The most common bug I observed is iterating from 0 to vector.size()-1 that for an empty vector is a huge number. Other possible bugs arise from the fact that a - b > 0 is not the same as a > b. Note that all this happens because unsigned for C++ means more or less "element of Z[n]" (Z[n] = integers modulo n) and has nothing to do with the sign. In your opinion does make sense that the number of elements in a vector is an element of that ring ? Unsigned ints are IMO indeed very useful... but NOT as quantities. – 6502 Jun 12 '10 at 21:48
  • 1
    OK, so you get an unexpected value. How is that better than getting an underflow? At least this way you're not mangling up your memory. – Lightness Races in Orbit Jul 10 '11 at 12:05
  • @Tomalak: Sorry? There is no reason in the world for which `v.size()-1` should be more or less four billions when `v` is empty... it should be 0-1=-1. Fullstop. The only reason this happen is because a wrong unsigned type has been used for the size of containers. This choice has nothing to do with being the logical thing, but is related only to historical reason on 16-bit architectures. Only people confused by an english meaning they attach to word "unsigned" think this is correct (and Bjarne Stroustrup is not one of them). The promotion and math rules are way more important than the name. – 6502 Jul 10 '11 at 14:14
0

But I think C++ must provide it.

Why? You think that C++ must provide the ability to make non-negative numbers negative? That's silly.

Unsigned values in C++ are defined to always be non-negative. They even wrap around — rather than underflowing — at zero! (And the same at the other end of the range)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055