C语言输出变量和表达式结果不一致问题

书里看到这样一个题目,让读者看看下面代码两次输出结果是否一致,为什么

int i = 0xcffffff3;
printf("%x\n", 0xcffffff3>>2);
printf("%x\n", i>>2);

输出结果

33fffffc
f3fffffc

下面列出分析思路。

  1. 移位结果计算
    0xcffffff3: 1100 1111 1111 1111 1111 1111 1111 0011
    右移两位后: 11 0011 1111 1111 1111 1111 1111 1100
    对应十六进制结果:
    33fffffc
  2. 那么f3fffffc是怎么来的呢?
    0xcffffff3:1100 1111 1111 1111 1111 1111 1111 0011
    0xf3fffffc:1111 0011 1111 1111 1111 1111 1111 1100
    对比0xcffffff3的二进制明显是右移时补位填1了
  3. 打印二者类型

将代码改为如下,执行

    int i = 0xcffffff3;
    printf("%x\n", 0xcffffff3>>2);
    printf("%x\n", i>>2);

结果

root@lssd:~/lumut/test_all# gcc xm.c -o xm -g -Wall
xm.c:15:6: warning: return type of ‘main’ is not ‘int[-Wmain]
   15 | void main()
      |      ^~~~
xm.c: In function ‘main’:
xm.c:24:14: warning: format ‘%s’ expects argument of type ‘char *, but argument 2 has type ‘unsigned int[-Wformat=]
   24 |     printf("%s\n", 0xcffffff3>>2);//33fffffc
      |             ~^     ~~~~~~~~~~~~~
      |              |     |
      |              |     unsigned int
      |              char *
      |             %d
xm.c:25:14: warning: format ‘%s’ expects argument of type ‘char *, but argument 2 has type ‘int[-Wformat=]
   25 |     printf("%s\n", i>>2);//f3fffffc
      |             ~^     ~~~~
      |              |      |
      |              char * int
      |             %d

显然移位表达式是无符号型,变量i是int型。
C语言定义int类型时,默认是有符号型,所以这里变量i首位是1,被处理为负数,负数右移补位有可能补0也有可能补1,x86平台的gcc编译器,最高位是移入1的。
而表达式0xcffffff3>>2中0xcffffff3首位是1,编译器处理成无符号整型,因为c的二进制首位是1,如果是有符号数,则会处理成负数。
5.验证上述思路,修改代码增加二进制首位不为1的十六进制数进行移位,如下:

    int i = 0xcffffff3;
    printf("%x\n", 0xcffffff3>>2);
    printf("%x\n", i>>2);
    printf("%s",i);
    printf("%s",0x0ffffff3);

结果

root@lssd:~/lumut/test_all# gcc xm.c -o xm -g
xm.c: In function ‘main’:
xm.c:26:14: warning: format ‘%s’ expects argument of type ‘char *, but argument 2 has type ‘int[-Wformat=]
   26 |     printf("%s",i);
      |             ~^  ~
      |              |  |
      |              |  int
      |              char *
      |             %d
xm.c:27:14: warning: format ‘%s’ expects argument of type ‘char *, but argument 2 has type ‘int[-Wformat=]
   27 |     printf("%s",0x0ffffff3);
      |             ~^  ~~~~~~~~~~
      |              |  |
      |              |  int
      |              char *
      |             %d

二者都是int型了。

5.总结
1.0x3ffffff3和0xcffffff3这两个常量虽然看起来差不多,但前者是int型,而后者是unsigned int型;
2.负数的移位运算应注意编译器运算的结果。

书籍:《Linux C编程一站式学习》 作者:宋劲杉

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值