Я запускаю следующий код на архитектуре Intel для настольных компьютеров x64 (компилятор 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;
где ссылка это QByteArray.
Я заметил, что, несмотря на приведение типа quint32 (который является беззнаковым int), мой 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
в unsigned int
(или другой больший тип без знака) язык определяет, что расширение знака происходит первым. Чтобы избежать этого, бросьте char
в unsigned char
как твой первый шаг. Вам не нужно никакого другого приведения — увеличение размера должно происходить автоматически.
Других решений пока нет …