Извлечение и вставка Chainging, брекетинг - PullRequest
3 голосов
/ 11 ноября 2019

Я пытался экспериментировать с этим странным поведением iostream.

int value = 2;

cout << (value << 2) << endl; //output is 8
cout << (value >> 2) << endl; //output is 0

Так что же здесь происходит?

Ответы [ 3 ]

2 голосов
/ 11 ноября 2019

Ваше замешательство здесь вполне понятно! Проблема связана с характером двух C++ операторов, << и >>. В самые первые дни эволюции языка от C это были исключительно , используемые в качестве так называемых операторов "сдвига битов", где << будет сдвигать значение в целое число на заданное числобиты влево, и >> будет сдвигать биты вправо. Итак, учитывая 2 для 16-разрядного целого числа, value, его двоичное представление будет:

0000000000000010

Выражение value << 2 сдвигает все биты в целых 2 местах на левый ;все биты, сдвинутые за «верх» (бит № 15), теряются, а «пробелы», созданные справа, заполняются нулями, давая:

0000000000001000

, что является двоичным представлением числа 8.

Выражение value >> 2 сдвигает все биты 2 на вправо ;все биты, сдвинутые за пределы «дна» (бит № 0), теряются, а пробелы справа заполняются нулями. Таким образом, в вашем случае, единственный бит 1 теряется (падает с конца), и общий value заканчивается как ноль.

Теперь, когда C++ концепция stream пришли, символы оператора были необходимы для ввода и вывода таких потоков (будь то string streams или file streams, например cout в вашем коде). Для них были выбраны операторы << и >>, так как они «выглядят» как то, что они на самом деле делают (стрелки-подобные индикаторы движения). К счастью, язык C++ позволяет переопределять из любого оператора для определенного типа переменной (это называется «перегрузка оператора») и, если вы посмотрите настандартный заголовок <iostream>, вы увидите что-то подобное в определении / объявлении класса ostream:

ostream& operator<< (int val);
//.. similar lines for types other than int

Эта «перегрузка оператора» кодируется в исходном коде стандартной библиотеки как запись отформатированноговерсия val для файла, представленного данным объектом ostream (например, cout).

Не стесняйтесь запрашивать дополнительные разъяснения и / или объяснения.

PS: Как провокатор упражнений / мыслей: что произойдет, если убрать скобки из двух строк кода?

PPS: Относительно использования битов- операторы сдвига для умножения или деления на степени 2: это лениво и потенциально опасно, когда может произойти смена знака;особенно для отрицательных чисел! См. cppreference.com (выделение жирным шрифтом):

Для отрицательного а поведение << b равно <strong>undefined .

Для беззнакового a и для подписанного и неотрицательного a значение a >> b является целой частью a / 2 ^ b.

Для отрицательного a значение a >> b равно * 1076. * определяется реализацией (в большинстве реализаций выполняется арифметическое смещение вправо, поэтому результат остается отрицательным).

1 голос
/ 11 ноября 2019

Краткий ответ: >> - это битовый оператор с правым сдвигом.

Длинный ответ: Числа на компьютерах обычно хранятся в двоичном формате, если у вас не 10, а только 2цифры: 0 и 1. В такой системе счисления у вас есть ноль как 0, один как 1, но 2 как 10, потому что первая цифра переполняется (цифра позади 1 отсутствует), три как 11, четыре как 100 и т. д.

Многие из языков программирования предлагают некоторые операции, действующие на двоичное представление чисел.

Есть некоторые из них:

  • bit-and &, который интерпретирует каждыйбит числа как отдельный логический элемент:
00000110
&
00000101
=
00000100

Здесь вы видите только третий бит в наборе результатов, равном 1, потому что это единственный бит, который установлен в 1 в первых двух числах.

  • бит или |, то есть операция || для отдельных битов операндов:
00000110
&
00000101
=
00000111

Здесь вы видите 1 бит в результате для любого бита, равного 1в любом из первых двух чисел.

  • сдвиг вправо >>, который «сдвигает» все битыs числа вправо на некоторое количество позиций:
00110100 >> 2
=
00001101
  • сдвиг влево <<, как и в предыдущем случае, но сдвигает биты влево:
00000101 << 3
=
00101000

Итак, изначально << и >> являются операторами сдвига битов. Но в C ++ у вас есть еще одна функция, называемая оператор перегрузки , которая позволяет вам переопределить поведение некоторых операторов для ваших конкретных типов. Вот некоторые примеры: operator + для строк, которые позволяют использовать + для «добавления» строк, например:

string a = "Hello";
string b = "World";
string c = a + ", " + b;

Строки не являются числами, но вы все равно можете использовать + для«добавление» (или сцепление) их, потому что кто-то уже определил такие перегрузки для +.

То же самое происходит с << и >>: это просто перегруженные операторы сдвига битов, определенные для вызовапри использовании с объектами cout и cin соответственно.

Некоторые ссылки для дальнейшего изучения:

1 голос
/ 11 ноября 2019

В случае потоков они являются операторами вставки и извлечения. В противном случае они известны как ЛЕВЫЕ И ПРАВЫЕ ОПЕРАТОРЫ. Читайте об этом из Ссылка Но пока позвольте мне объяснить ваш вывод.

(<<) (сдвиг влево) Принимает два числа, сдвигает влево биты первого операндавторой операнд определяет количество мест для сдвига. Или, другими словами, сдвиг влево целого числа «x» с целым числом «y» эквивалентно умножению x на 2 ^ y (2 повышают до степени y). </p>

Например -

 a = 5//(00000101)
 a<<1
result is 10(00001010)>// here bit shifted by one position.

(>>) (правое смещение) Принимает два числа, сдвигает вправо биты первого операнда, второй операнд определяет количество мест для сдвига. Аналогично правое смещение (x >> y) эквивалентноделению x на 2 ^ y.

a = 5;//(00000101)
The result is 00000010 which is 2
printf("b>>1 = %d\n", b>>1); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...