【问题标题】:bitwise NOT of signed and unsigned integers in CC中有符号和无符号整数的按位非
【发布时间】:2017-03-28 23:47:36
【问题描述】:

我正在调试一个问题,并发现以下 sn-p(sanitized) 是问题的原因。

uint64_t testflag = 0;
testflag &= ~(0x08ul); //bug 
testflag &= ~(0x08l);  //expected 

我比较了生成的程序集,看到了这个

  uint64_t testflag = 0;
804851e:    c7 45 d8 00 00 00 00    movl   $0x0,-0x28(%ebp)
8048525:    c7 45 dc 00 00 00 00    movl   $0x0,-0x24(%ebp)
  testflag &= ~(0x08ul);
804852c:    83 65 d8 f7             andl   $0xfffffff7,-0x28(%ebp)
8048530:    83 65 dc 00             andl   $0x0,-0x24(%ebp)
  testflag &= ~(0x08l);
8048534:    83 65 d8 f7             andl   $0xfffffff7,-0x28(%ebp)
8048538:    83 65 dc ff             andl   $0xffffffff,-0x24(%ebp)

为什么unsigned longNOT operator 会导致编译器将0 与更高的字节而不是ffffffff 进行AND。

我的 gcc 版本是 gcc (GCC) 4.9.2 (Red Hat 4.9.2) 在 64 位机器上。

【问题讨论】:

  • 什么是sizeof(unsigned long)
  • 符号扩展与零扩展,因为 long 在您的机器上是 32 位。

标签: c gcc signed


【解决方案1】:

假设 32 位 unsigned long/long...

uint64_t testflag;

 0x08ul     --> 00 00 00 08
 ~(0x08ul)  --> FF FF FF F7
some_uint32_t = FF FF FF F7 

testflag &= some_uint32_t;
testflag = testflag & some_uint32_t
testflag = testflag & (uint64_t) some_uint32_t
testflag = testflag & (uint64_t) FF FF FF F7  (or 4,294,967,288)
testflag = testflag & 00 00 00 00 FF FF FF F7 

将 32 位无符号转换为 uint64_t 只是简单的 0 扩展。


现在~(0x08l)

 0x08l      --> 00 00 00 08
 ~(0x08l)   --> FF FF FF F7
some_int32_t  = FF FF FF F7 

testflag &= some_int32_t;
testflag = testflag & some_int32_t
testflag = testflag & (uint64_t) some_int32_t
testflag = testflag & (uint64_t)  FF FF FF F7 (or - 8)
testflag = testflag & FF FF FF FF FF FF FF F7 (or 18,446,744,073,709,551,608)

-8 作为uint64_t 非常接近uint64_t 的最大值。
使用 2 的补码,结果是 OP 的 long 的符号位被扩展。 @Marc Glisse

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-24
    • 2019-04-07
    • 1970-01-01
    • 2013-10-02
    • 2012-02-11
    • 1970-01-01
    • 2015-02-17
    • 2013-09-01
    相关资源
    最近更新 更多