Ответ 1
Проблема в 1<<31
. Поскольку 2 31 не может быть представлено с 32-разрядным знаковым целым числом (диапазон -2 31 до 2 31 - 1), результат undefined [1].
Исправить легко: 1U<<31
.
[1]: поведение определяется реализацией с С++ 14.
Я написал следующую программу для вывода двоичного эквивалента целочисленного значения (я проверил, что int в моей системе имеет 4 байта), он имеет 4 байта. Но выход не подходит. Код:
#include<iostream>
#include<iomanip>
using namespace std;
void printBinary(int k){
for(int i = 0; i <= 31; i++){
if(k & ((1 << 31) >> i))
cout << "1";
else
cout << "0";
}
}
int main(){
printBinary(12);
}
Где я ошибаюсь?
Проблема в 1<<31
. Поскольку 2 31 не может быть представлено с 32-разрядным знаковым целым числом (диапазон -2 31 до 2 31 - 1), результат undefined [1].
Исправить легко: 1U<<31
.
[1]: поведение определяется реализацией с С++ 14.
Это выражение неверно:
if(k & ((1<<31)>>i))
int
является подписанным типом, поэтому, когда вы сдвигаете 1
31 раз, он становится битом знака в вашей системе. После этого смещение результата right i
times sign - увеличивает число, что означает, что верхние бит остаются 1
s. Вы получите последовательность, которая выглядит так:
80000000 // 10000...00
C0000000 // 11000...00
E0000000 // 11100...00
F0000000 // 11110...00
F8000000
FC000000
...
FFFFFFF8
FFFFFFFC
FFFFFFFE // 11111..10
FFFFFFFF // 11111..11
Чтобы исправить это, замените выражение на 1 & (k>>(31-i))
. Таким образом, вы избежите поведения undefined * вызванного сдвигом 1
в позицию знакового бита.
*С++ 14 изменил определение, чтобы сдвинуть 1
31 раз влево в 32-битном int
больше не undefined (Спасибо, Мэтт Макнабб, за это указали).
Типичное представление внутренней памяти знакового целочисленного значения выглядит следующим образом:
m ost s b он (первый справа) - это знаковый бит и
signed numbers
(например,int
) он представляет, является ли число отрицательным или нет. Когда вы переносите дополнительные биты Расширение знака выполняется для сохранения знака числа. Это делается с помощью добавления цифр к наиболее значимой стороне числа. (В соответствии с процедурой, зависящей от конкретного используемого имени числа).
В беззнаковых числах первый бит из правой представляет собой только MSB представленного числа, поэтому, когда вы переносите дополнительные биты, расширение знака не выполняется.
Примечание: перечисление бит начинается с 0, поэтому 1 << 31
заменяет ваш бит знака, и после этого каждая операция сдвига бит влево >>
приводит к расширению знака. (как указывает @dasblinkenlight)
Итак, простое решение вашей проблемы состоит в том, чтобы сделать число без знака (это то, что U
делает в 1U << 31
), прежде чем вы начнете манипулировать бит. (как указывает @Yu Hao)
Для дальнейшего чтения см. подписанные представления числа и два дополнения.(as это наиболее распространенный)