位运算反向转换ulong值结果不符合预期问题排查
字节缓冲区转ulong无法还原原始值的问题
问题代码
ulong us = (ulong)(millisecondsSinceUnixEpoch * 1000.0); // xxxxxxxx-xxxx-0000-0000-000000000000 _buffer[0] = (byte)(us >> 40); _buffer[1] = (byte)(us >> 32); _buffer[2] = (byte)(us >> 24); _buffer[3] = (byte)(us >> 16); _buffer[4] = (byte)(us >> 8); _buffer[5] = (byte)us; ulong reUs = ((ulong)_buffer[0] << 40) | ((ulong)_buffer[1] << 32) | ((ulong)_buffer[2] << 24) | ((ulong)_buffer[3] << 16) | ((ulong)_buffer[4] << 8) | _buffer[5]; Debug.WriteLine(us); Debug.WriteLine(reUs);
输出结果
1691334871851000 (us)
2485011587064 (reUs)
预期结果:reUs == us
错误原因
- 字节长度不足:
ulong是64位(8字节)类型,但代码仅用6个字节存储数据,导致原始值的高16位被直接丢弃,还原时无法恢复这部分信息。从输出结果可看出,reUs正好是原始us的低48位数值,高16位信息完全丢失。 - 位运算类型隐患:还原代码中
_buffer[5]未强制转换为ulong,当该字节值大于127时,会被自动提升为带符号的int类型,符号扩展后再转ulong会产生错误的高位数据,进一步导致结果偏差。
修正方案
方案1:用8字节缓冲区存储完整ulong值
若需完整还原ulong,必须使用8字节缓冲区存储全部64位数据:
// 拆分完整ulong到8字节缓冲区 _buffer[0] = (byte)(us >> 56); _buffer[1] = (byte)(us >> 48); _buffer[2] = (byte)(us >> 40); _buffer[3] = (byte)(us >> 32); _buffer[4] = (byte)(us >> 24); _buffer[5] = (byte)(us >> 16); _buffer[6] = (byte)(us >> 8); _buffer[7] = (byte)us; // 还原完整ulong ulong reUs = ((ulong)_buffer[0] << 56) | ((ulong)_buffer[1] << 48) | ((ulong)_buffer[2] << 40) | ((ulong)_buffer[3] << 32) | ((ulong)_buffer[4] << 24) | ((ulong)_buffer[5] << 16) | ((ulong)_buffer[6] << 8) | (ulong)_buffer[7];
方案2:仅存储高48位并还原(匹配注释格式)
若需求是仅存储ulong的高48位(对应注释的GUID前缀格式),需调整移位逻辑保留高48位信息:
// 拆分高48位到6字节缓冲区 ulong high48Bits = us >> 16; _buffer[0] = (byte)(high48Bits >> 40); _buffer[1] = (byte)(high48Bits >> 32); _buffer[2] = (byte)(high48Bits >> 24); _buffer[3] = (byte)(high48Bits >> 16); _buffer[4] = (byte)(high48Bits >> 8); _buffer[5] = (byte)high48Bits; // 还原高48位并补全低16位(需确保原始值低16位为0,否则无法完整还原) ulong reUs = (((ulong)_buffer[0] << 40) | ((ulong)_buffer[1] << 32) | ((ulong)_buffer[2] << 24) | ((ulong)_buffer[3] << 16) | ((ulong)_buffer[4] << 8) | (ulong)_buffer[5]) << 16;
内容的提问来源于stack exchange,提问作者Tiago Conceição
相关产品推荐
相关产品推荐

