在不同的体系结构上转换指针类型

Casting pointer types on different architectures

我有以下结构和 "getter" 函数 returns a 转换为无符号整数:

struct s {
    uint32_t a;
};

void get_a(struct s *st, unsigned *ret)
{
    *ret = (unsigned)st->a;
}

下面的代码是运行:

struct s st;
uint16_t x;

st.a = 1;
get_a(&st, (unsigned *)&x);

并且对于 x86_64、i686、armv7hl、ppc64le 和其他架构 x == 1,但对于 ppc64 x == 0。为什么是这样?小端还是大端?

问题是您有:

uint16_t x;

但随后您尝试写入该内存位置,就好像它是 unsigned 的位置一样。

如果您在 unsigneduint16_t 是同一类型的系统上,这很好。但是在其他系统上,例如您用于代码示例的系统,您就有麻烦了。

首先,这导致undefined behaviour by violating the strict aliasing ruleuint16_t 类型的变量只能通过 uint16_t 类型的左值或字符类型写入。

但即使它没有违反严格的别名,你仍然会在 x 的范围之外写入导致 UB。可能您正在将 4 或 8 个字节写入 2 字节的内存位置,因此它会溢出缓冲区。

如果 x 对于 unsignedaligned 不正确,也可能存在 UB。