在工作碰到好几次不同type的integer/value比较出错,导致奇怪的bug。很小的问题,却不容忽视。
看几个例子.原来我的想法是他们bitwise level是一样的,这4个比较应该都是true才对。
char m_costBasis1;
UINT1 m_costBasis2;//define unsigned char UINT1
UINT2 l_BasisNum; //define unsigned short UINT2
如果assign 2给这三个变量
m_costBasis1 == l_BasisNum //true
m_costBasis2 == l_BasisNum //true
如果assign 176给这三个变量 (>=127)
m_costBasis1 == l_BasisNum //false (-80 vs 176)
m_costBasis2 == l_BasisNum //true
安全的做法,当然是避免这种相同意义的东西有不同type的定义。不过木已成舟,如果这种定义来自数据库,很可能就改不了了;一个可以的work around是做explicit convert。
但是windows上的compiler为什么跟我想的不一样呢?在说答案之前,先上点原理。
为了提高本帖的理论深度和技术含量,贴上几段关于implicit numberical convert的权威说明。具体说明了convert的几条原则以及他们间的优先级。
http://en.cppreference.com/w/cpp/language/implicit_cast
Prvalues of small integral types (such as char) may be converted to prvalues of larger integral types (such asint). In particular,arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied. This conversion always preserves the value.
The following implicit conversions are classified as integral promotions:
signed char
or signed short
can be converted toint.unsigned char
or unsigned short
can be converted toint if it can hold its entire value range, andunsignedint otherwise.char
can be converted to int orunsignedint depending on the underlying type: signed char or unsignedchar (see above)http://en.cppreference.com/w/cpp/language/operator_arithmetic
the operand has integer type (because bool, char, char16_t, char32_t, wchar_t, and unscoped enumeration were promoted at this point) andintegral conversions are applied to produce the common type, as follows:
The conversion rank above increases in order bool,signedchar, short,int,long,longlong. The rank of any unsigned type is equal to the rank of the corresponding signed type. The rank ofchar is equal to the rank ofsignedchar and unsignedchar. The ranks of char16_t,char32_t, andwchar_t are equal to the ranks of their underlying types.
http://en.cppreference.com/w/cpp/language/operator_comparison
以上说的是standard的convert的原则,但是microsoft的实现是不一样的;看下面。
http://msdn.microsoft.com/en-us/library/09ka8bxx%28v=vs.100%29.aspx
If the preceding three conditions are not met, and if either operand is of typeunsigned int, the other operand is converted to typeunsigned int.
If none of the preceding conditions are met, both operands are converted to typeint.
如果看完上面的,估计你也知道答案了。
按照cppreference的说法,这4处确实都是true的,因为会promote成unsigned int;
但是miscrosoft的做法,比较简单,都是int。所以char中的-80(就是unsigned short的176)会变成-80的int;但是176的unsigned short变成176的int,当然有false的情况。