免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: glq2000
打印 上一主题 下一主题

为何 #define ISUNSIGNED(a) (a>=0 && ~a>=0) 有问题(判断是否有符号) [复制链接]

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
31 [报告]
发表于 2010-06-14 14:08 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
32 [报告]
发表于 2010-06-14 14:46 |只看该作者
这里似乎分成 理论派 和 实践派 了
hellioncu 发表于 2010-06-14 13:24



    我晕,什么是理论?什么是实践?

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-05-27 06:20:00
33 [报告]
发表于 2010-06-14 16:33 |只看该作者
回复 30# churchmice

恩 我也试了下 unsigned short 以及 unsigned char型的变量, (a>=0 && ~a>=0) 果然无法判断他们,原因正如你所说,他们被提升为int了。 多谢

那对于这个问题,大家有没有针对ANSI c的解决方案呢? 不一定要用宏,只要解决问题即可

论坛徽章:
0
34 [报告]
发表于 2010-06-14 19:39 |只看该作者

  1. #include <stdio.h>

  2. const int issn_shift[9] = { 0, 7, 15, 0, 31, 0, 0, 0, 63 };

  3. int main()
  4. {
  5. #define ISSN(x) ( x<0? 1: \
  6.                 (x^=(1<<issn_shift[sizeof(x)]))<0? \
  7.                         (x^=(1<<issn_shift[sizeof(x)]),1) : \
  8.                         (x^=(1<<issn_shift[sizeof(x)]),0) )
  9.         int i;
  10.         unsigned int j;
  11.         short ss;
  12.         unsigned short us;
  13.         char sc;
  14.         unsigned char uc;

  15.         for( i=0; (unsigned int) i != 0xffffffff; (unsigned int) i++ )
  16.         {
  17.                 if(! ISSN(i) )
  18.                 {
  19.                         printf("int error %d\n",i);
  20.                         return -1;
  21.                 }
  22.         }
  23.         for( j=0; j != 0xffffffff; j++ )
  24.         {
  25.                 if( ISSN(j) )
  26.                 {
  27.                         printf("unsigned int error %u\n",j);
  28.                         return -1;
  29.                 }
  30.         }
  31.         for( ss=0; (unsigned short) ss != 0xffff; (unsigned short) ss++ )
  32.         {
  33.                 if(! ISSN(ss) )
  34.                 {
  35.                         printf("short error %d\n",ss);
  36.                         return -1;
  37.                 }
  38.         }
  39.         for( us=0; us != 0xffff; us++ )
  40.         {
  41.                 if( ISSN(us) )
  42.                 {
  43.                         printf("unsigned short error %u\n",us);
  44.                         return -1;
  45.                 }
  46.         }
  47.         for( sc=0; (unsigned char) sc != 0xff; (unsigned char) sc++ )
  48.         {
  49.                 if(! ISSN(sc) )
  50.                 {
  51.                         printf("char error %d\n",sc);
  52.                         return -1;
  53.                 }
  54.         }
  55.         for( uc=0; uc != 0xff; uc++ )
  56.         {
  57.                 if( ISSN(uc) )
  58.                 {
  59.                         printf("unsigned char error %u\n",uc);
  60.                         return -1;
  61.                 }
  62.         }
  63.         return 0;
  64. }
复制代码

论坛徽章:
0
35 [报告]
发表于 2010-06-14 19:48 |只看该作者
本帖最后由 没本 于 2010-06-14 21:26 编辑

  1. #define ISSN(x) ( x<0? 1: \
  2.                 (x^=(1<<issn_shift[sizeof(x)]))<0? \
  3.                         (x^=(1<<issn_shift[sizeof(x)]),1) : \
  4.                         (x^=(1<<issn_shift[sizeof(x)]),0) )
复制代码
不能优化成

  1. #define ISSN(x) ( x<0? 1: \
  2.                 (x^(1<<issn_shift[sizeof(x)]))<0? 1 : 0 )
复制代码
会报short error 0。应该用x本身进行比较。

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
36 [报告]
发表于 2010-06-14 21:09 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
37 [报告]
发表于 2010-06-14 21:15 |只看该作者
wuliao

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
38 [报告]
发表于 2010-06-14 21:21 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
39 [报告]
发表于 2010-06-15 21:02 |只看该作者
讨论的有深度。

论坛徽章:
0
40 [报告]
发表于 2010-06-17 11:13 |只看该作者
解决:
#define ISUNSIGNED(a) ( (a < 0) ? 0 : (a = ~a) >= 0 ? \
         (a = ~a, 1) : (a = ~a, 0) )

原因解析:

K&R C所采用无符号保留(unsigned preserving)原则,就是当一个无符号类型与int或更小的整型混合使用时,结果类型是无符号类型。这是个简单的规则,与硬件无关。但是,正如下面的例子所展示的那样,它有时会使一个负数丢失符号位。
ANSI C标准则采用值保留(value preserving)原则,就是当把几个整型操作数像下面这样混合使用时,结果类型有可能是有符号数,也可能是无符号数,取决于操作数的类型的相对大小。
下面的程序段分别在ANSI C和K&R C编译器中运行时,将打印出不同的信息:
main(){
  if(-1 < (unsigned char)1
     printf("-1 is less than (unsigned char)1: ANSI semantics ");
  else
     printf("-1 NOT less than (unsigned char)1: K&R semantics");
}
程序中的表达式在两种编译器下编译的结果不同。-1的位模式是一样的,但一个编译器(ANSI C)将它解释为负数,另一个编译器(K&R C)却将它解释为无符号数,也就是变成了正数。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP