Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Некорректная работа операции сдвига


Автор: bsa 4.3.2010, 15:12
Код
#include <iostream>

int main()
{
    unsigned x;
    unsigned y = 32;
    unsigned mask = 1 << 31;
    x = mask << y;
    std::cout << std::hex << "0x" << x << " 0x" << (unsigned(1) << 32) << " 0x" << mask << " 0x" << y << std::endl;
}
Этот код, собранный gcc, выдает у меня:
Код
0x80000000 0x0 0x80000000 0x20
Хотя, по идее, должен выдавать 0 первым числом.

Я что-то не знаю?

Автор: Albor 4.3.2010, 15:41
Вот это, второе значение выводит как 0х0
Код

std::cout << std::hex << "0x" <<((unsigned) x) << " 0x" << ((0x80000000) << 32) << " 0x" << mask << " 0x" << y << std::endl;

А вот это - как 0х80000000
Код

std::cout << std::hex << "0x" <<((unsigned) x) << " 0x" << ((0x80000000) << y) << " 0x" << mask << " 0x" << y << std::endl;

Получается, что данный глюк происходит из-за переменной

Добавлено @ 15:44
Хе, а при y=31  выдаёт 0

Автор: bsa 4.3.2010, 16:27
кстати. я в примере ошибся с направлением операции сдвига. Нужно использовать сдвиг вправо в строке 8.
Код
#include <iostream>
int main()
{
    unsigned x;
    unsigned y = 32;
    unsigned mask = 1 << 31;
    unsigned z = mask >> (y-1);
    x = mask >> y;
    std::cout << std::hex << "0x" << x << " 0x" << (unsigned(1) << 32) << " 0x" << mask << " 0x" << y << " 0x" << z << std::endl;
}
Выводит:
Код
0x80000000 0x0 0x80000000 0x20 0x1

Автор: Albor 4.3.2010, 16:32
Выходит, что без разницы куда сдвигать на у, и так и эдак получается один и тот же результат

Автор: borisbn 4.3.2010, 18:44
Из стандарта C++
Код

The behavior is undefined if the right operand is negative, or greater than or equal to
the length in bits of the promoted left operand


У меня msvc, и ваш код выглядет в ассемблере следующим образом
Код

; 58   :     x = mask >> 32;

  00492    8b 4d e0     mov     ecx, DWORD PTR _mask$[ebp]
  00495    c1 e9 20     shr     ecx, 32            ; 00000020H
  00498    89 4d e4     mov     DWORD PTR _x$[ebp], ecx

; 59   :     x = 1 << 32;

  0049b    c7 45 e4 00 00
    00 00         mov     DWORD PTR _x$[ebp], 0


Автор: bsa 4.3.2010, 20:43
borisbn, цитаты из стандарта достаточно для меня. Спасибо.

Автор: xvr 7.3.2010, 16:52
Цитата

У меня msvc, и ваш код выглядет в ассемблере следующим образом

Интересует код для x = mask << y;. Скорее всего там shl ?,ecx, где в ecx будет загружен y. Насколько я помню, IA32 использует в операциях shl/shr только 5 младших битов ecx. Так что 32 в y(а значит и в ecx) для него эквивалентны 0


Автор: borisbn 7.3.2010, 17:17
xvr, вы верно предположили про cx (правда cl, а не ecx, но думаю это не играет роли)
Код

; 55   :     x = mask << y;    

  00469    8b 45 e0     mov     eax, DWORD PTR _mask$[ebp]
  0046c    8b 4d e8     mov     ecx, DWORD PTR _y$[ebp]
  0046f    d3 e0         shl     eax, cl
  00471    89 45 e4     mov     DWORD PTR _x$[ebp], eax


Цитата(xvr @  7.3.2010,  16:52 Найти цитируемый пост)
Насколько я помню, IA32 использует в операциях shl/shr только 5 младших битов ecx

получается на другом процессоре это может работать по-другому?

Автор: mes 7.3.2010, 17:18
Цитата(borisbn @  7.3.2010,  16:17 Найти цитируемый пост)
получается на другом процессоре это может работать по-другому?

 smile , поэтому стандарт и не предписывает определенного поведения в этом вопросе.

Автор: xvr 7.3.2010, 17:21
Цитата(borisbn @ 7.3.2010,  17:17)
получается на другом процессоре это может работать по-другому?

Угу, стандарт тут по этому поводу уже цитировали - behavior is undefined

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)