Как мне использовать побитовые сдвиги с cout? - PullRequest
0 голосов
/ 01 июня 2019

Я пытаюсь сделать что-то похожее на это:

#include <iostream>

int main()
{
    std::cout << 1 << 5 << std::endl;
}

Я ожидаю 32 (1 сдвинут влево на 5), но я получаю 15.

Я пытаюсь использовать такой макрос:

#define BIT_SHIFT(x,y) x << y
...
cout << BIT_SHIFT(1, 5) << std::endl;

и это происходит.

Почему? Как мне это исправить?

Ответы [ 3 ]

6 голосов
/ 01 июня 2019

Просто используйте паратезы.

#include <iostream>

int main()
{
    std::cout << (1 << 5) << std::endl;
}

std::cout << 1 << 5 означает «выдать потоку первый целочисленный литерал 1, за которым следует целое число 5». Однако добавление паразитов изменяет порядок оценки, и 1 << 5 вычисляется первым, что приводит к выражению std::cout << 32 << std::endl;.

5 голосов
/ 01 июня 2019

Используйте скобки:

    std::cout << (1 << 5) << std::endl;

Причина заключается в том, что перегрузка ostream& operator<<(ostream&, const T&) на выходе связывает возвращаемые значения, чтобы вызвать функцию еще раз.

Если вы используете круглые скобки, сначала вычисляется значение смещения битов, а затем передается перегруженному оператору вывода.


Я пытаюсь использовать это в макросе: ...

Таким образом, вышеупомянутое определение вашего макроса должно выглядеть так:

#define BIT_SHIFT(x,y) ((x) << (y))

Вы можете задаться вопросом, почему теперь дополнительные скобки. Это просто безопаснее писать макросы. Подумайте о том, что кто-то пытается использовать ваш макрос, например:

 cout << BIT_SHIFT(1, 5*2) << std::endl;
0 голосов
/ 01 июня 2019

Я пытаюсь сделать что-то похожее на это:

#include <iostream>

int main()
{
   std::cout << 1 << 5 << std::endl;
}

Ты прав. Вы пытаетесь сделать что-то похожее на это. Однако проблема не имеет ничего общего с макросом (я имею в виду, что это тоже проблема, но об этом позже). Проблема в том, что ваша цель не в том, что вы имеете в виду. Вы не имеете в виду std::cout << 1 << 5 << std::endl;, вы имеете в виду std::cout << (1 << 5) << std::endl; Разница в том, что первое разбивается на что-то вроде этого:

std::cout << 1;
std::cout << 5;
std::cout << std::endl;

Пока вы хотите что-то вроде этого:

int i = 1 << 5;

std::cout << i;
std::cout << std::endl;

Или что-то на этот счет.

Ответ прост: либо используйте круглые скобки в своем выражении cout, либо вставьте их в свой макрос (лучший вариант):

// either 
cout << (BIT_SHIFT(1, 5)) << std::endl;
// or
#define BIT_SHIFT(x,y) (x << y)
...
cout << BIT_SHIFT(1, 5) << std::endl;

Кроме того, как кто-то еще предложил, вы можете даже пойти на шаг дальше, если хотите, и сделать это:

#define BIT_SHIFT(x,y) ((x) << (y))
...
cout << BIT_SHIFT(1, 5) << std::endl;

Таким образом, если вы делаете что-то странное в x или y, ваш код не ломается.

...