How to type-pun in C

JL2*_*210 -1 c z80 emulation type-punning

Follow-up to extended discussion in Casting behavior in C

I'm trying to emulate a Z80 in C, where several 8-bit registers can be combined to create 16-bit registers.

This is the logic I'm trying to use:

struct {
    uint8_t b;
    uint8_t c;
    uint16_t *bc;
} regs[1];
...
regs->bc = (uint16_t *)&(regs->b);
Run Code Online (Sandbox Code Playgroud)

Why is this incorrect, and how can I do it correctly (using type-punning if needed)?

I need to do this multiple times, preferably within the same structure.

For those of you that I haven't mentioned this to: I understand that this assumes a little-endian architecture. I have this handled completely.

Lun*_*din 7

这是不正确的,因为b它的类型uint8_t和指向的指针uint16_t不能用于访问此类变量。它可能未正确对齐,并且是严格的别名冲突

但是,您可以自由执行(uint8_t *)&regs(struct reg_t*)&regs->b,因为(6.7.2.1/15)

指向适当转换的结构对象的指针指向其初始成员,反之亦然。


在进行与硬件相关的编程时,请确保不要使用带符号的类型。这意味着更改intn_tuintn_t

至于如何正确键入pun,请使用并集:

typedef union
{
  struct                 /* standard C anonymous struct */
  {
    uint8_t b;
    uint8_t c;
  };
  uint16_t bc;
} reg_t;
Run Code Online (Sandbox Code Playgroud)

然后可以将其分配为指向16位硬件寄存器,如下所示:

volatile reg_t* reg = (volatile reg_t*)0x1234;
Run Code Online (Sandbox Code Playgroud)

0x1234硬件寄存器地址在哪里。

注意:此联合是与病情相关的。b将访问bc大字节序系统上的MS字节,但bc访问小字节序系统上的LS字节。