JavaScript按位屏蔽

这个问题与其他问题类似, 不过,我想了解为什么这样工作。

以下代码:

console.log((parseInt('0xdeadbeef', 16) & parseInt('0x000000ff', 16)).toString(16)); console.log((parseInt('0xdeadbeef', 16) & parseInt('0x0000ff00', 16)).toString(16)); console.log((parseInt('0xdeadbeef', 16) & parseInt('0x00ff0000', 16)).toString(16)); console.log((parseInt('0xdeadbeef', 16) & parseInt('0xff000000', 16)).toString(16)); console.log((parseInt('0xdeadbeef', 16) & parseInt('0x000000ff', 16)).toString(16)); console.log((parseInt('0xdeadbeef', 16) & parseInt('0x0000ffff', 16)).toString(16)); console.log((parseInt('0xdeadbeef', 16) & parseInt('0x00ffffff', 16)).toString(16)); console.log((parseInt('0xdeadbeef', 16) & parseInt('0xffffffff', 16)).toString(16)); 

返回:

 ef be00 ad0000 -22000000 ef beef adbeef -21524111 

当我期望从.string(16)将是:

 ef be00 ad0000 de000000 ef beef adbeef deadbeef 

这是怎么回事?

预先感谢您的帮助。


感谢下面的回应者和评论者,以及以下来源:

  • http://speakingjs.com/es5/ch11.html
  • JavaScript C风格types从签名转换为无符号

这是一个解决scheme,通过提供工具函数来将基数为16的32位数字转换为带符号的32位整数:

 // Convert 'x' to a signed 32-bit integer treating 'x' as a radix-16 number // cf http://speakingjs.com/es5/ch11.html function toInt32Radix16(x) { return (parseInt(x, 16) | 0); } // Convert a signed 32-bit integer 'x' to a radix-16 number // cf https://stackoverflow.com/questions/14890994/javascript-c-style-type-cast-from-signed-to-unsigned function toRadix16int32(x) { return ((x >>> 0).toString(16)); } console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x000000ff'))); console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x0000ff00'))); console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x00ff0000'))); console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0xff000000'))); console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x000000ff'))); console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x0000ffff'))); console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0x00ffffff'))); console.log(toRadix16int32(toInt32Radix16('0xdeadbeef') & toInt32Radix16('0xffffffff'))); 

这产生了预期的输出:

 ef be00 ad0000 de000000 ef beef adbeef deadbeef 

以及关于JavaScript整数行为的一些很好的学习。

在JavaScript中,所有按位运算(和其中的& )都返回有符号的32位整数,结果在-2 31到2 31 -1(含)范围内。 这就是为什么你现在有多一点( 0xde000000大于0x7ffffff )表示一个符号,这意味着你会得到一个负值。

一个可能的修复:

 var r = 0xdeadbeef & 0xff000000; if (r < 0) { r += (1 << 30) * 4; } console.log( r.toString(16) ); // 'de000000' 

因为按位操作(如& )是在javascript中的带符号的 32位整数完成的。 所有位被设置的0xFFFFFFFF实际上是-1 ,而你期望的0xde000000实际上是-570425344