Неожиданный вывод при побитовой операции правого сдвига
int main()
{
int x = 0xff0000ff;
int N_BITS = sizeof (int) * 8; /* 32 */
int l = 0x0;
printf ("Right shift expected result: %xn", 0x80000000 >> (31));
l = (x & (0x00000001 << (N_BITS - 1)));
printf ("l = %xn", l);
/* Right Shift l by 31 bits */
l = l >> 31;
printf ("l after right shift by 31 bits: %xn", l);
}
~
Вывод:
Right shift expected result: 1
l = 80000000
l after right shift by 31 bits: ffffffff
~
Сдвиг вправо 0x80000000 на 31 бит должен привести к 0x00000001, как показано в самом первом выводе. Почему выходные данные отличаются здесь, когда переменная l
смещена на 31 бит вправо?
1 ответ:
Предполагая результат
l = (x & (0x00000001 << (N_BITS - 1)));
Является
0x80000000
(см. ниже это не гарантируется, так как выражение вызывает неопределенное поведение).В системе дополнения двойки,
0x80000000
является отрицательным значением (INT_MIN
).l = l >> 31;
C говорит, что эта операция
>>
определена реализацией. В вашей системе он выполняет расширение знака: знаковый бит распространяется.(C11, 6.5. 7p4) " если E1 имеет знаковый тип и отрицательное значение, то результирующее значение равно реализация-определена."
Наконец, почему:
0x000001 << (N_BITS - 1)
Вызывает неопределенное поведение.
Из уст лошади (Курсив мой):
(C11, 6.5. 7p4) " результатом E1 Если E1 имеет знак тип и неотрицательное значение, а также E1 × 2^^E2 представимо в типе результата, то есть результирующее значение; в противном случае поведение не определено. "