是否有可能创建两个uint8_t指针指向uint16_t指针指向的值的第一个和第二个半?

我正在尝试用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可能在技术上导致未定义的行为.

点赞