Question

I am running the following code on an Desktop x64 Intel architecture (gcc compiler, linux) and on an RaspberryPi Arm (gcc cross compiler).

quint32 id;

id=((quint32)ref[1]);
id|=((quint32)ref[2])<<8;
id|=((quint32)ref[3])<<16;
id|=((quint32)ref[4])<<24;

where ref is a QByteArray.

I noticed, that despite of casting quint32 (which is unsigned int) my Pc do the sign extension which causes error, when the given byte is a negative number. My code runs fine on Arm. Why does this happens? I thought casting should prevent this. Doesn't it?

   id|=((quint32)ref[4])<<24;

disassembly:

    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)

I have also noticed, that compiler uses QByteRef return value instead of char. But it should not cause any error i guess.

from QByteArray help page :

QByteRef    operator[](int i)
char    operator[](int i) const
QByteRef    operator[](uint i)
char    operator[](uint i) const

Thanks in advance

Était-ce utile?

La solution

When converting from a signed char to unsigned int (or other larger unsigned type) the language specifies sign extension happens first. To avoid that, cast the char to unsigned char as your first step. You shouldn't need any other cast - the increase in size should happen automatically.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top