我具有以下结构和“getter”函数,该函数将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导致strict aliasing rule。只能通过uint16_t类型或字符类型的左值写入uint16_t类型的变量。

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

如果x对于unsigned而言不是正确aligned,则也可能存在UB。

关于在不同架构上强制转换指针类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31607620/

10-11 22:37
查看更多