【问题标题】:Wrong sign extension c++/qt错误的符号扩展 c++/qt
【发布时间】: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;

其中 refQByteArray

我注意到,尽管强制转换 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


【解决方案1】:

当从有符号的char 转换为unsigned int(或其他更大的无符号类型)时,语言指定符号扩展首先发生。为避免这种情况,第一步将char 转换为unsigned char。你不应该需要任何其他演员 - 尺寸的增加应该自动发生。

【讨论】:

    猜你喜欢
    • 2013-08-17
    • 2013-10-16
    • 2020-07-13
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多