最近我问了一个问题:Replace byte in a int
,它显示了如何替换整数上的字节。 我也需要使用Int64做同样的事情。显然我对这个哈哈很不好。我不知道为什么将int替换为Int64并不能使它工作。换句话说,我将最后一个问题的解决方案修改为:
static Int64 ReplaceByte1( int index , Int64 value , byte replaceByte )
{
return ( value & ~( 0xFF << ( index * 8 ) ) ) | ( replaceByte << ( index * 8 ) );
}
static Int64 ReplaceByte2( int index , Int64 value , byte replaceByte )
{
// how many bits you should shift replaceByte to bring it "in position"
var shiftBits = 8 * index;
// bitwise AND this with value to clear the bits that should become replaceByte
Int64 mask = ~( 0xff << shiftBits );
// clear those bits and then set them to whatever replaceByte is
return value & mask | ( replaceByte << shiftBits );
}
在使用大值时不起作用。例如,将方法调用为:
// returns 12345678848 where it should return 3755744309
var test1 = ReplaceByte1( 4 , 12345678901 , 0 );
// returns 12345678848 where it should return 3755744309
var test2 = ReplaceByte2( 4 , 12345678901 , 0 );
我怎样才能使它与Int64一起使用?我究竟做错了什么?唯一有效的方法是最后一个最慢的方法。
我已经进行了替换,但仍然得到了不同的结果。为什么?看一看:
// method that words
static Int64 SlowReplace ( int index , Int64 value , byte replaceByte )
{
var bytes = BitConverter.GetBytes( value );
bytes[ index ] = replaceByte;
return BitConverter.ToInt64( bytes , 0 );
}
static Int64 ReplaceByte1 ( int index , Int64 value , byte replaceByte )
{
return ( value & ~( (long)0xFF << ( index * 8 ) ) ) | ( replaceByte << ( index * 8 ) );
}
static Int64 ReplaceByte2 ( int index , Int64 value , byte replaceByte )
{
// how many bits you should shift replaceByte to bring it "in position"
var shiftBits = 8 * index;
// bitwise AND this with value to clear the bits that should become replaceByte
Int64 mask = ~( ( Int64 )0xff << shiftBits );
// clear those bits and then set them to whatever replaceByte is
return value & mask | ( replaceByte << shiftBits );
}
static void Main ( string[ ] args )
{
var a = SlowReplace( 4 , 12345678901 , 255 ); // 1098972404789 corect
var b = ReplaceByte1( 4 , 12345678901 , 255 ); // 3755744511 incorrect
var c = ReplaceByte2( 4 , 12345678901 , 255 ); // 3755744511 incorrect
Console.Read( );
}
答案 0 :(得分:2)
问题现在依赖于replaceByte << shiftBits
表达式。
请参阅<< Operator
documentation。
文档说明如果第一个操作数是32位数量(在这种情况下是,因为对byte
变量执行了隐式转换),移位计数由低位给出 - 命令第二个操作数的五位。在这种情况下,因为shiftBits
等于32 = 2 ^ 5,二进制表示为100000,低位五位为00000。
除了显式广告((long)0xFF
)之外,您还可以使用l
或L
后缀常量,将其标记为long
/ Int64
(或ul
/ UL
ulong
/ UInt64
},0xFFL
/ replaceByte << shiftBits
可以认为{{1}}不太美观/可读。对于{{1}}情况,需要显式强制转换。
答案 1 :(得分:1)
您需要将常量0xff
强制转换为long
:
Int64 mask = ~( (Int64)0xff << shiftBits );
如果您不这样做并且index
大于3,那么mask
将会有错误的值,因为文字0xff
是int
并且还有this rule:
如果第一个操作数是int或uint(32位数量),则移位 count由第二个操作数的低位五位给出。那 是,实际移位计数是0到31位。
由于在这种情况下移位计数是2的幂并且大于31,所以它的低位5位将全部为零,这将导致根本没有移位(就像shiftBits == 0
)。因此mask
将具有错误的值,并且会清除value
中的错误位,从而产生错误的结果。
答案 2 :(得分:0)
将0xFF << ( index * 8 )
替换为(long)0xFF << ( index * 8 )