【发布时间】:2014-03-23 00:21:04
【问题描述】:
我在 Desktop x64 Intel 架构(gcc 编译器、linux)和 RaspberryPi Arm(gcc 交叉编译器)上运行以下代码。
quint32 id;
id=((quint32)ref[1]);
id|=((quint32)ref[2])<<8;
id|=((quint32)ref[3])<<16;
id|=((quint32)ref[4])<<24;
其中 ref 是 QByteArray。
我注意到,尽管强制转换 quint32(它是无符号整数),但当给定字节为负数时,我的 PC 会执行导致错误的符号扩展。我的代码在 Arm 上运行良好。为什么会发生这种情况? 我认为投射应该可以防止这种情况发生。不是吗?
id|=((quint32)ref[4])<<24;
反汇编:
mov -0x160(%rbp),%rax
mov $0x4,%esi
mov %rax,%rdi
callq 0x425af0 <QByteArray::operator[](int)>
mov %rax,%rcx
mov %edx,%eax
mov %rcx,-0x170(%rbp)
mov %eax,-0x168(%rbp)
mov -0x170(%rbp),%rax
mov %rax,-0x40(%rbp)
mov -0x168(%rbp),%rax
mov %rax,-0x38(%rbp)
lea -0x40(%rbp),%rax
mov %rax,%rdi
callq 0x425aa0 <QByteRef::operator char() const>
movsbl %al,%eax #sign extension.
shl $0x18,%eax
or %eax,-0x148(%rbp)
我还注意到,编译器使用 QByteRef 返回值而不是 char。但我猜它不应该导致任何错误。
来自QByteArray帮助页面:
QByteRef operator[](int i)
char operator[](int i) const
QByteRef operator[](uint i)
char operator[](uint i) const
提前致谢
【问题讨论】:
-
在我看来,您列出了 不能 导致问题的一行,因为所有符号位都会从顶部移出。否则,我可以看到平台之间可能存在差异,具体取决于底层
char定义是签名还是未签名。 -
为什么不使用 QDataStream 并以这种方式从 QByteArray 读取 uint32?
-
确实第四位不会导致任何错误,我只是复制了错误的汇编示例。我认为,char signess 不应该打扰我,因为在转换之前强制转换 uint 强制不使用符号扩展。我错了吗?当然我可以使用 id|=(((quint32)ref[2]) & 0xff)
-
艾伦斯托克斯所说的。
标签: c++ qt gcc sign-extension