判断一个变量是有符号数还是无符号数(转)
《C专家编程》最后一段讲面试,说是微软曾经有一道面试题:写一段代码,确定一个变量是有符号数还是无符号数?
首先,任何试图用函数来解决此问题的方法都不好使,因为函数有类型检查,所以只能用宏啦。
书中给出了一个宏:#define ISUNSIGNED(a) (a>=0 && ~a>=0)
它只能用在K&R C里,在ANSI C里就不行了。当这个宏被用在int/unsigned int时,没有任何问题。但是在判断unsigned char和unsigned short上就会出错。
此宏在int/unsigned int好使的原因是宏中的a的精度始终不会发生变化,而当a是char和short时,表达式~a>=0会先将a变为int然后再取反(因为常量0的类型为int),而int当然是有符号的,对它取反就有可能小于0。
要修正这个错误其实很简单,那就是要保证先进行取反操作再做精度提升,我们可以采用对a取反a=~a(这样就不会有类型提升),判断结束后再取一次反,恢复a的值。
好了,上测试代码:
#define IS_SIGNED_NUM(a) (a < 0 ? true :( a =~a,a < 0 ? (a=~a,true):(a=~a,false))) #define IS_UNSIGNED_NUM(a) (a >=0 && (a=~a,a >=0 ? (a=~a,true):(a=~a,false))) void testSignedNum() { int a1 = 0xffff0001; int a2 = 0x0fff0001; int a =0; unsigned int b1 = 0xffff0001; unsigned int b2 = 0xffff0001; unsigned int b =0; assert(IS_SIGNED_NUM(a1) == true && IS_UNSIGNED_NUM(a1) == false); assert(IS_SIGNED_NUM(a2) == true && IS_UNSIGNED_NUM(a2) == false); assert(IS_SIGNED_NUM(a) == true && IS_UNSIGNED_NUM(a) == false); assert(IS_SIGNED_NUM(b1) == false && IS_UNSIGNED_NUM(b1) == true); assert(IS_SIGNED_NUM(b2) == false && IS_UNSIGNED_NUM(b2) == true); assert(IS_SIGNED_NUM(b) == false && IS_UNSIGNED_NUM(b) == true); char a3 = -1; char a4 = 0x0f; char a5 = 0; unsigned char b3 = 0xff; unsigned char b4 = 0x0f; unsigned char b5 = 0; assert(IS_SIGNED_NUM(a3) == true && IS_UNSIGNED_NUM(a3) == false); assert(IS_SIGNED_NUM(a4) == true && IS_UNSIGNED_NUM(a4) == false); assert(IS_SIGNED_NUM(a5) == true && IS_UNSIGNED_NUM(a5) == false); assert(IS_SIGNED_NUM(b3) == false && IS_UNSIGNED_NUM(b3) == true); assert(IS_SIGNED_NUM(b4) == false && IS_UNSIGNED_NUM(b4) == true); assert(IS_SIGNED_NUM(b5) == false && IS_UNSIGNED_NUM(b5) == true); }
---------------------------------------------------------------
参考文献:《C专家编程》