You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言中用位移位拼接uint8为uint16的代码异常排查

问题分析与解决

这个问题的核心是Go语言中整数类型的溢出行为和类型转换时机和C语言存在差异,导致你的位操作结果不符合预期。

问题根源拆解

先看你的Go代码:

func DereferenceWord(addr uint32) uint16 { 
    return uint16(memoryPointer[addr]) | uint16(memoryPointer[addr + 1] << 8) 
}

这里的memoryPointer[addr + 1]是uint8类型(8位无符号整数),当你执行<< 8操作时:

  • uint8的取值范围是0~255,二进制仅占8位,左移8位后所有有效位都会被移出,结果直接变成0
  • 之后再把这个0转成uint16,数值依然是0
  • 最后和uint16(memoryPointer[addr])(也就是0xff)做按位或,结果自然是0xff

而你的C代码:

uint16_t connect(uint8_t a, uint8_t b) { return (uint16_t) a | (uint16_t) b << 8; }

这里是先把b转成uint16(16位)再左移8位,左移后b的二进制是0xff00,再和a的0x00ff按位或,得到正确的0xffff。

修正后的Go代码

只需要调整类型转换的时机,先把uint8转成uint16再做左移操作:

func DereferenceWord(addr uint32) uint16 { 
    return uint16(memoryPointer[addr]) | (uint16(memoryPointer[addr+1]) << 8) 
}

或者为了可读性更清晰,可以拆分步骤:

func DereferenceWord(addr uint32) uint16 {
    lowByte := uint16(memoryPointer[addr])
    highByte := uint16(memoryPointer[addr+1]) << 8
    return highByte | lowByte
}

这样当两个字节都是0xff时,highByte会是0xff00,和lowByte的0x00ff按位或后,就能得到正确的0xffff。

额外验证

对比你的SetWord函数,它是先把uint16的data拆分高低位存到内存里,逻辑完全正确:先右移0位取低8位,再右移8位取高8位。修正后的DereferenceWord刚好是这个过程的逆操作,完全匹配内存存储规则。

内容的提问来源于stack exchange,提问作者Safal Aryal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:07:00