1. mixing unsigned and sign int is a bad idea
- first of all, remember: signed int types will be implicitly converted to unsigned if sizeof(signed int types) == sizeof(unsigned int types)
- Google C++ coding standard, say “do not use unsigned integer”
- C++ STL using
size_t
which isunsigned int
to represent size of containters like std::vector, std::string - do not assume sizeof(int types), always #
include <stdint.h>
and use int64_t - compiler can warn
warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
. However, mixed unsigned and signed int algorithm is not warned - JAVA before Java 8 SE does not support unsigned int, even in Java 8 SE you can not declare unsigned int types, but only using static methods, unsigned comparison.
There are good reason not to supported it. - python built-in integer/long is unsigned, but
ctypes
module defined c++ unsigned types; python 3 integer will not overflow - see also
http://blog.robertelder.org/signed-or-unsigned-part-2/
example and explanation from stackoverflow
2. Relevant quote from the Standard: Expressions
10 Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are de?ned as follows:
2 clauses about equal types or types of equal sign omitted
- Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.
- Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.
- Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.
3. pitfall of overflow and underflow
- overflow detection can not been done by compiler but user
- float overflow could be captured and hook to abort routine
- avoiding infinite looping for underflow by compiler warning
comparison of unsigned expression >= 0 is always true [-Wtype-limits]
- assigned minus int to unsigned int should be prohibited, try hex instead or UINT_MAX – 1, since compiler will not warn you for implicit conversion into unsigned int types
4. pitfall of implicit conversion
see more c and c++ pitfalls
- implicit conversion from bool to int:
-0.5 < x < 0.5
- implicit conversion int bool to pointer: must decleare ctor(ptr) as explicit in c++11, and using null_ptr
- c++11 smart ptr like shared_ptr<> will not convert to raw ptr!
- http://en.cppreference.com/w/cpp/language/implicit_conversion
Guru of the Week (GotW)
Guru of the Week (GotW) is a series of C++ programming problems created and written by Herb Sutter.
#include <iostream> #include <limits> #include <vector> void std_container_test(){ std::vector<int> v; int i = 10; if (i < v.size()-1) // there is a compiler warning here std::cout <<"underflow occurs for empty container size()-1\n"; } void underflow_test(int input_s, unsigned int input_u){ unsigned int size_u = 10u; unsigned int i_u; int size_s = 10; int i_s; // infinite looping for underflow for(i_u = size_u -1; i_u >=0; i_u--){ std::cout <<"unsigned: " << ((input_u + i_u) / 2u) << "\n"; } } void float_overflow_test() { float d = std::numeric_limits<float>::max(); std::cout << "std::numeric_limits<float>::max() = " << d << std::endl; float q = d + 100; //behavior is undefined, could be inf, or remained as std::numeric_limits<float>::max() std::cout << "q: " << q << std::endl; } void bool_implicit_coversion_pitfall_test() { int x = 0; if (!(-0.5 <= x <= 0.5)) std::cout << "x=0, -0.5 <= x <= 0.5 is false"<<"\n"; } void signed_int_test() { signed int s1 = -4; unsigned int u1 = 2; signed long long s2 = -4; unsigned int u2 = 2; signed long long int s3 = -4; unsigned long int u3 = 2; unsigned long int u4 = -2; // no worning at all if (s1>u1) std::cout << s1 << " > " << u1 << " is true? \n"; std::cout << (s1 + u1) << "\n"; // 4294967294 std::cout << (s2 + u2) << "\n"; // -2 std::cout << (s3 + u3) << "\n"; // 18446744073709551614 std::cout << " What are you expecting from `unsigned long int u4 = -2;`, actually stored integer is " << u4<< "\n"; } int main() { signed_int_test(); bool_implicit_coversion_pitfall_test() ; std_container_test(); float_overflow_test(); }