在不同的体系结构上转换指针类型
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
的位置一样。
如果您在 unsigned
和 uint16_t
是同一类型的系统上,这很好。但是在其他系统上,例如您用于代码示例的系统,您就有麻烦了。
首先,这导致undefined behaviour by violating the strict aliasing rule。 uint16_t
类型的变量只能通过 uint16_t
类型的左值或字符类型写入。
但即使它没有违反严格的别名,你仍然会在 x
的范围之外写入导致 UB。可能您正在将 4 或 8 个字节写入 2 字节的内存位置,因此它会溢出缓冲区。
如果 x
对于 unsigned
的 aligned 不正确,也可能存在 UB。
我有以下结构和 "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
的位置一样。
如果您在 unsigned
和 uint16_t
是同一类型的系统上,这很好。但是在其他系统上,例如您用于代码示例的系统,您就有麻烦了。
首先,这导致undefined behaviour by violating the strict aliasing rule。 uint16_t
类型的变量只能通过 uint16_t
类型的左值或字符类型写入。
但即使它没有违反严格的别名,你仍然会在 x
的范围之外写入导致 UB。可能您正在将 4 或 8 个字节写入 2 字节的内存位置,因此它会溢出缓冲区。
如果 x
对于 unsigned
的 aligned 不正确,也可能存在 UB。