我正在尝试用C编写Gameboy模拟器,目前我正在决定如何实现以下行为:
>可以组合两个8位寄存器,并将其视为一个16位寄存器
>更改配对中其中一个8位寄存器的值应更改组合寄存器的值
例如,寄存器A和F是8位寄存器,可以共同用作16位寄存器AF.但是,当寄存器A和F的内容发生变化时,这些变化应反映在后续的寄存器AF中.
如果我将寄存器AF实现为uint16_t *,我可以将寄存器A和F的内容存储为uint8_t *分别指向寄存器AF的第一个和第二个字节吗?如果没有,任何其他建议将不胜感激:)
编辑:只是为了澄清,这是一个与Z80非常相似的架构
最佳答案 使用工会.
union b
{
uint8_t a[2];
uint16_t b;
};
成员a和b共享字节.当在成员a中写入值然后使用成员b读取时,将在此类型中重新解释该值.这可能是一个陷阱表示,会导致未定义的行为,但类型uint8_t和uint16_t没有它们.
另一个问题是字节顺序,写入成员a的第一个元素将始终更改成员b的第一个字节,但取决于字节可能代表b的大部分或最低有效位的字节顺序,因此结果值将因架构而异.
要避免陷阱表示和字节序,而是仅使用类型uint16_t并使用按位运算写入它.例如,要写入最重要的8位:
uint16_t a = 0;
uint8_t b = 200;
a = ( uint16_t )( ( ( unsigned int )a & 0xFF ) | ( ( unsigned int )b << 8 ) ) ;
类似地,对于最不重要的8位:
a = ( uint16_t )( ( ( unsigned int )a & 0xFF00 ) | ( unsigned int )b );
这些操作应该放在一个函数中.
转换为(unsigned int)是为了避免整数提升.如果INT_MAX等于2 ^ 15-1,并且存在有符号整数的陷阱表示,则操作:b<< 8可能在技术上导致未定义的行为.