Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using unsigned int vs. checking if negative

Tags:

Say I have a class with an integer that should be always positive with a simple C'tor:

class A {     unsigned int x;     public:     A(unsigned int X) : x(X) {} }; 

And lets say someone accidentally creates an A object with the value -5. Of course, this is not valid and X will get a really huge value since the MSB now doesnt stand for the number sign. Problem is, that now I can't really check if the number is negative or invalid (maybe bitwise?).

Should I just avoid the unsigned and just use a plain int? By doing so, i could just throw an exception if the given value is beyond a max value OR below zero.

Would love to hear some suggestions.

like image 989
Rouki Avatar asked Sep 18 '13 06:09

Rouki


People also ask

How do you check if an unsigned int is negative?

Check for an equivalent negative int value only requires checking the highest bit, if it is 1 , then that unsigned number would be represented as a negative int value -- but you would have to further check that the value does not exceed INT_MIN before proceeding with any such conversion, otherwise you need to extend to ...

What is the advantage of using unsigned int?

The advantage to using the unsigned version (when you know the values contained will be non-negative) is that sometimes the computer will spot errors for you (the program will "crash" when a negative value is assigned to the variable). We will talk more about assigning and using uints later in class.

Is it good practice for unsigned int?

Unsigned is good programming practice to indicate the intention, to yourself and others, of use of the data element - just in the same way all types are used. For example, a normal array index variable should never be negative and so declaring the variable unsigned should be best practice.

When should you use the unsigned int?

An n-bit unsigned variable has a range of 0 to (2n)-1. When no negative numbers are required, unsigned integers are well-suited for networking and systems with little memory, because unsigned integers can store more positive numbers without taking up extra memory.


2 Answers

Two approaches come to mind:

  1. Add an explicit conversion for the 'signed' types.

    #include <cassert>  class A {     unsigned int x;     public:     A(unsigned int X) : x(X) {}     explicit A(int X) : x(static_cast<unsigned>(X)) {         assert(X>=0); // note X, not x!     } };  int main() {     A ok(5);     A bad(-5); } 
  2. Prohibit implicit conversions by deleting better overloads:

    A(int X) = delete; A(long X) = delete; A(char X) = delete; 

    This will require all users to cast to unsigned before constructing the A instance. It's safe but clumsy.

Note that this does not prohibit implicit conversions from all integral types (e.g. enums) so you'd need to do more to make this fool proof.

Here is a rudimentary SFINAE-based example that accepts all implicit conversions except if they involve signed values: Live on Coliru

#include <type_traits> #include <limits>  class A {     unsigned int x;     public:     template<typename T, typename = typename std::enable_if<std::is_integral<T>::value, void>::type>     A(T X) : x(X)     {         static_assert(!std::numeric_limits<T>::is_signed, "Signed types cannot be accepted");     } };  int main() {     A ok(5u);     A bad(-5); } 
like image 182
sehe Avatar answered Nov 02 '22 23:11

sehe


And lets say someone accidentally creates an A object with the value -5

While it may be good practice to make your program robust enough to accept such errors, the root cause of the bug is a sloppy programmer who does not have sufficient warnings enabled.

To get to the bottom of the problem, you need to ensure that the code is compiled with all warnings enabled, and perhaps also consider using an external static analysis tool.

like image 39
Lundin Avatar answered Nov 02 '22 22:11

Lundin