S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

  确定一个变量是有符号数还是无符号数 收藏
读《C专家编程》,其中一段讲面试,说是微软曾经有一道面试题:
写一段代码,确定一个变量是有符号数还是无符号数?

书上给出了两个宏:
#define ISUNSIGNED(a) (a>=0 && ~a>=0)
#define ISUNSIGNED(type) ((type)0-1 > 0)

第二个从类型来判断,没有问题。

而第一个只能用在K&R C里,在ANSI C里就不行了。
当这个宏被用在int/unsigned int时,没有任何问题。
但是当使用在char和short上就会出错。

ANSI C中的整型升级:
char,short int或者int型位段(bit-field),包括它们的有符号或无符号变型,
以及枚举类型,可以使用在需要int或unsigned int的表达式中,
如果int可以完整地表示源类型的所有值,那么该类型的值就转换为int,否则转换为unsigned int。

ANSI C中的寻常算术转换:
当执行算术运算时,操作数的类型如果不同,就会发生转换。
数据类型一般朝着浮点精度更高、长度更长的方向转换,
整型数如果转换为signed不会丢失信息,就转换为signed,否则就转换为unsigned。
这个称为值保留(value preserving)原则。

所以,无论原先是否有符号,char和short都被转换成了signed int(整型升级)。
原先unsigned的东西变成了signed,然后再进行取反。
同时,常数0被认为是signed int类型,所以一律被判为有符号数了。

问题是一旦char或者short参与了运算,它们将被首先转换成int,
在这以后,任何操作都变成徒劳的了,int永远都是signed。
那么能否在整型升级之前让signed char/short变成负数呢?至少我现在还没想到办法。

偶使用了赖皮方法,无耻地定义了全局变量,还用了变态的逗号表达式……

于是第一个宏就变成下面这个样子了:
int r, t;
#define ISUNSIGNED(a) (t = a, r = (a>=0 && (a=~a)>=0), a = t, r)
再一想,既然用了全局变量保存a的值,还讨论干啥?于是……

int r, t;
#define ISUNSIGNED(a) (t = a, r = ((a=-1) >= 0), a = t, r)

而且这样做的前提是,假设int是最长的整型类型,并且是有符号的。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yysdsyl/archive/2007/11/14/1885829.aspx


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/rainbow_free/archive/2009/06/17/4275697.aspx

Feedback

# re: 确定一个变量是有符号数还是无符号数[未登录]  回复  更多评论   

2010-05-12 09:44 by wonder
#define ISUNSIGN(A) ((A>0)&&( ((A=~A,A>0)&&(A=~A,1)) || (A=~A,0) ))

# re: 确定一个变量是有符号数还是无符号数[未登录]  回复  更多评论   

2012-04-10 20:10 by 小强
#define right(type) ( (type)((type)0 - 1) > 0) 就可以了,这个表达式生成全1的位字段,有符号的话就是-1,无的话就是2^k - 1,能确保正确工作

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理