Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.96/462: Рейтинг темы: голосов - 462, средняя оценка - 4.96
0 / 0 / 0
Регистрация: 13.12.2014
Сообщений: 4

Как работают побитовые сдвиги?

13.04.2007, 19:36. Показов 88452. Ответов 58
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Люди объясните плиз как работают побитовые сдвиги
<< и >>, а то что то совсем запарился :confused:
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.04.2007, 19:36
Ответы с готовыми решениями:

Побитовые сдвиги
#include&lt;iostream&gt; int main() { int t=1; while(255&amp;t){ t=t&lt;&lt;t; std::cout&lt;&lt;t&lt;&lt;'\n';} ...

Побитовые сдвиги
Был на собеседовании, была задачка, вроде такая: Есть функция, которая принимает char a (1 байт) Нужно определить количество битов,...

Побитовые сдвиги
нужна помощь с заданием на С++: При написании функций можно использовать только следующее: - целочисленные константы; - целочисленные...

58
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
26.12.2017, 23:10
Студворк — интернет-сервис помощи студентам
Байт, у которого включен только один бит RXEN можно написать следующими способами:

C++
1
2
3
4
0b00010000
0x10
(1<<4)
16
Записи-то одни и те же, просто по форме отличаются.
Включить его можно с помощью логического побитового или
C++
1
UCSRB |= (1<<4);
Выключить - сделав логическое побитовое и для маски, в которой все кроме этого бита единицы
C++
1
UCSRB &= 0b11101111;
или то же самое, но с вычислением этой маски компилятором, с помощью побитового "не":
C++
1
UCSRB &= ~(1<<4);
Переключить его в некой переменной можно через Xor (поскольку для остальных битов 1^0 даст 1, а 0^0 даст 0)
C++
1
UCSRB ^= (1<<4);

Добавлено через 2 минуты
Цитата Сообщение от design_m Посмотреть сообщение
Но везде пишут не
Но ведь позицию сдвига - 4 - намного проще запомнить, вот её и задефайнили в макросе RXEN. Вот и будешь писать вместо (1<<4) - (1<<RXEN). Чем если бы задефанили именно маску данного бита.

Добавлено через 7 минут
Потому что все подобные константные выражения компилятор считает сам, и записывает в машинный код уже в виде готового числа.
1
0 / 0 / 0
Регистрация: 30.06.2015
Сообщений: 209
27.12.2017, 01:15
Цитата Сообщение от TRam_ Посмотреть сообщение
UCSRB |= (1<<4);
так ведь
Цитата Сообщение от TRam_ Посмотреть сообщение
(1<<RXEN)
это же не одно и то же.
Просто этот способ верен, только если RXEN равен 0, а если в предыдущей операции его состояние изменилось на "1", то мне почему-то кажется, что
он в "0" установится, только установив одновременно в 1 следующий разряд.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
27.12.2017, 01:30
Цитата Сообщение от design_m Посмотреть сообщение
биты 7-0 RXCIE TXCIE UDRIE RXEN TXEN UCSZ2 RXB8 TXB8 регистра UCSRB
биты этого регистра могут только включаться/выключаться, бегать же они не могут, так?

А если не могут, то куда по-твоему должен убежать бит RXEN ? Или смещение этого бита, записанное в RXEN ?

Добавлено через 1 минуту
Цитата Сообщение от design_m Посмотреть сообщение
это же не одно и то же
при записи
C++
1
2
3
#define RXEN 4
 
UCSRB |= (1<<RXEN);
одно и то же

Добавлено через 2 минуты
Цитата Сообщение от design_m Посмотреть сообщение
если в предыдущей операции его состояние изменилось на "1", то мне почему-то кажется, что
он в "0" установится
"1" или "0" равно "1". На остальные разряды это не повлияет, т.к. это не "прибавить 1"
1
0 / 0 / 0
Регистрация: 30.06.2015
Сообщений: 209
27.12.2017, 01:44
так если
Цитата Сообщение от TRam_ Посмотреть сообщение
#define RXEN 4
не может быть равен 4? Он же может быть равен только 0 и 1?
если это бит?

Добавлено через 2 минуты
Цитата Сообщение от TRam_ Посмотреть сообщение
На остальные разряды это не повлияет, т.к. это не "прибавить 1"
не понял. Если это сдвиг, так как он на остальные разряды не влияет? Он же сдвигается влево? Разве не так?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
27.12.2017, 02:44
в записи (1<<RXEN) он двигает единицу из состояния
C++
1
0b00000001
в состояние (влево, 4 раза переставляя)
C++
1
0b00010000
Ничто другое он не двигает.

Добавлено через 3 минуты
А в записи
C++
1
UCSRB |= (1<<RXEN);
он накладывает на текущее состояние регистра UCSRB
C++
1
2
3
4
5
0b11000010
|
0b00010000
=
0b11010010
(по такому принципу)
1
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,875
27.12.2017, 09:37
Цитата Сообщение от design_m Посмотреть сообщение
они не могут быть 5 и 1, это не регистры, а биты.
а теперь смотрим на определение и видим что то типа
C
1
#define  RXEN 5// или какое другое число
это не регистры и не биты а порядок бита в управляющем байте
делают так чтобы с меньшей кровью переходить с камня на камень
в микроконтроллерах тема не раз обсуждалась

Добавлено через 1 минуту
Цитата Сообщение от design_m Посмотреть сообщение
а должны быть установлены биты
кому должны?
это аппаратно зависимые биты и каждый зависит от конкретного типа микроконтроллера
1
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,538
Записей в блоге: 1
27.12.2017, 09:46
так я хочу понять, в чем тут дело, ведь если эти биты не равны 0, то эта запись не установит их в 1?
эта запись никакие биты не выставляет в этой записи сам регистр даже не участвует в выражении ValeryS всё правильно написал - RXEN это всего лишь цифра 5
Биты регистра изменяются когда ты пишешь UCSRB = UCSRB | маска нужных битов
0
0 / 0 / 0
Регистрация: 30.06.2015
Сообщений: 209
27.12.2017, 15:28
Цитата Сообщение от TRam_ Посмотреть сообщение
в записи (1<<RXEN) он двигает единицу из состояния
C++
Выделить код
1
0b00000001
в состояние (влево, 4 раза переставляя)
C++
Выделить код
1
0b00010000
так это я знаю, (кстати, откуда взялась цифра "4"? Там 1 или 0)

То есть 1 может быть сдвинута 1 или 0 раз влево, судя по записи.

вопрос то не об этом.
Просто так устанавливать бит в 1, не трогая соседние, получается, только когда этот бит (RXEN)== 0. A если он уже ==1, то тогда соседний бит (слева) установится в 1? (Ну например, в результате предыдущей операции , которая уже установила RXEN==1?)

Добавлено через 3 минуты
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
RXEN это всего лишь цифра 5
не понимаю, как бит RXEN может быть цифрой "5", даже логически цифра 5 может состоять только из 2х битов? Тем более, что бит разве может иметь значение кроме 0 и 1?

Добавлено через 7 минут
Но в принципе, я догадался - просто если инициализируют USART, то в первый раз всё так и есть, по умолчанию он ==0, а 2й раз уже инициализировать не придётся, поэтому на возможность того, что он уже может быть раньше поставлен в 1, не обращают внимания. ТОгда действительно, писать имя бита удобнее , чем я раньше старался всегда писать в бинарном формате типа
C#
1
0b00011000
.
0
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,538
Записей в блоге: 1
27.12.2017, 15:35
Цитата Сообщение от design_m Посмотреть сообщение
Просто так устанавливать бит в 1, не трогая соседние, получается, только когда этот бит (RXEN)== 0. A если он уже ==1, то тогда соседний бит (слева) установится в 1? (Ну например, в результате предыдущей операции , которая уже установила RXEN==1?)
Так мы не UCSRB сдвигаем. Мы сдвигаем единицу. Если тебе настолько сложно воспринять обсуждаемое выражение, распиши его по действиям. 1) Сдвиг единицы 2) ИЛИ старого значения USCRB с маской 3) присвоение нового значения USCRB

Боже, прочитай уже книжку по Си, наконец! Какой смысл тут что-то непрофессионально объяснять тебе третью страницу подряд, если всё уже давно объяснили гораздо более умные люди в книгах?!?!
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
27.12.2017, 16:10
Цитата Сообщение от design_m Посмотреть сообщение
То есть 1 может быть сдвинута 1 или 0 раз влево, судя по записи
1 в данном случае сдвигается влево на 4 позиции (или 4 раза на одну позицию, если так понятнее). И все нули перед этой 1 тоже сдвигаются влево 4 раза, самые-самые левые при этом теряются. А справа добавляются новые нули. итого из 00000001 получается 00010000. Если бы мы проводили этот сдвиг не с 1, а например с 57, то из 00111001 получилось бы 1001000.

Сам регистр USART в этом действии не участвует, оно проводится ещё до того, как компилятор запишет машинный код скомпилированной программы. Как раз для получения того самого числа 00011000 . Которое на других моделях микроконтроллеров может быть например 01100000 или каким-то ещё. Но если написано (1<<RXEN)|(1<<TXEN), то вычислением данного числа займётся компилятор согласно уже выставленным разработчиками библиотеки к данному микроконтроллеру значениям RXEN и TXEN.
1
0 / 0 / 0
Регистрация: 30.06.2015
Сообщений: 209
27.12.2017, 17:13
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Боже, прочитай уже книжку по Си, наконец!
я читал здесь https://learnc.info/c/bitwise_operators.html но если есть лучше, кинь ссылку пожалуйста.
Цитата Сообщение от TRam_ Посмотреть сообщение
1 в данном случае сдвигается влево 4 раза.
Но откуда 4? Это же номер разряда, а значение бита же не может быть таким?
Скинь пожалуйста ссылку, где написано это?
(я прочитав про битовые сдвиги, раньше думал, что (1<<RXEN) обозначает сдвинуть 1 из 4 разряда влево 0 раз, т.е. 4 разряд установится в 1). А если бы он был ==1, то 1 раз, и тогда 5 бит установится в 1, а в с 4 по 0 биты допишутся нули?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
27.12.2017, 17:38
Цитата Сообщение от design_m Посмотреть сообщение
(я прочитав про битовые сдвиги, раньше думал, что (1<<RXEN) обозначает сдвинуть 1 из 4 разряда влево 0 раз, т.е. 4 разряд установится в 1)
оператор битового сдвига двигает все разряды операнда влево (либо вправо) на указанное число разрядов, заполняя "освобождённые" разряды нулями. Никакой "замены местами" значений соседних разрядов по указанному номеру разряда речи никогда не было, и подобного оператора по-умолчанию не существует (хотя его можно реализовать функцией, из нескольких операций).

Именно поэтому для него удобно использовать 1цу, потому что над сдвигами нулей в прочих разрядах можно не задумываться, а думать только над перемещениями этой самой единицы по разрядам.

Добавлено через 6 минут
Цитата Сообщение от design_m Посмотреть сообщение
обозначает сдвинуть 1 из 4 разряда влево 0 раз
На самом деле значит сдвинуть 1 из нулевого разряда (а где ещё она должна быть когда всё значение 1 ? ) в 4 разряд. Ноль перед этой единицей сдвинуть в 5 разряд. И т.д.
1
0 / 0 / 0
Регистрация: 30.06.2015
Сообщений: 209
27.12.2017, 19:16
Цитата Сообщение от TRam_ Посмотреть сообщение
Но если написано (1<<RXEN)|(1<<TXEN), то вычислением данного числа займётся компилятор согласно уже выставленным разработчиками библиотеки к данному микроконтроллеру значениям RXEN и TXEN.
так а где это написано? я хотел бы весь этот текст прочитать?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
27.12.2017, 19:46
Касательно значений в RXEN и TXEN ?
Если судить по http://forum.cxem.net/index.ph... регистрах/ то в файле "mega16_bits.h" или аналогичном, сгенерированном студией для вашего микроконтроллера при создании проекта.

Если качательно вычислений выражений из констант, то http://citforum.ru/programming... _043.shtml или https://it.wikireading.ru/35113

Добавлено через 9 минут
И ещё здесь можете посмотреть http://mycpp.ru/cpp/book/c04.html, в особенности раздел "побитовые операторы"
1
0 / 0 / 0
Регистрация: 30.06.2015
Сообщений: 209
28.12.2017, 11:49
Так-то я читал примерно это
Цитата Сообщение от design_m Посмотреть сообщение
https://learnc.info/c/bitwise_operators.html
но в основном везде встречаю описания просто С в общем виде, а специфика микроконтроллера там же не учитывается

Цитата Сообщение от TRam_ Посмотреть сообщение
Касательно значений в RXEN и TXEN ?
так я имел в виду теорию, так как в этом заголовочном файле просто написаны определения, а мне хочется узнать, почему это так? Вы сами, например, где это прочитали? Скиньте ссылку, пожалуйста.

(Просто я раньше всё время думал, что это просто отдельно адресуемые биты, (как в ассемблере в некоторых регистрах есть отдельно адресуемые биты). Т.е. я думал, что можно присвоить этим битам отдельно значения, не трогая весь остальной регистр. )
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
28.12.2017, 12:28
Цитата Сообщение от design_m Посмотреть сообщение
а мне хочется узнать, почему это так?
Берите datasheet на микроконтроллер и смотрите расположение и значение битов регистров в нём.

Добавлено через 3 минуты
Никакой теории в этом нет - просто разработчики кристалла микроконтроллера запроектировали, что 4 бит такого-то регистра отвечает за открытие/закрытие получения данных по UART.

Добавлено через 4 минуты
Цитата Сообщение от design_m Посмотреть сообщение
я думал, что можно присвоить этим битам отдельно значения, не трогая весь остальной регистр
ну вот для этого и используется операция "|=". То есть

C++
1
UCSRB |= 0b00010000;
эквивалентно
C++
1
UCSRB = UCSRB | 0b00010000;
и, как видно, при этой операции все 0 и 1, которые были в битах UCSRB, сохранятся. За исключением 4го.
1
0 / 0 / 0
Регистрация: 30.06.2015
Сообщений: 209
28.12.2017, 13:21
Цитата Сообщение от TRam_ Посмотреть сообщение
смотрите расположение и значение битов регистров в нём.
Так я и так это знаю, там выше Как работают побитовые сдвиги?написал.

Но просто не пойму, как это, сдвигая 1 можно не трогать остальные биты в регистре? Когда он пустой, это понятно
C
1
0b00000001 -> 0b0010000 //shift 00000001 4 times
а теперь если опять сдвигать 1 из 0 разряда 3 раза, так 4-й разряд уедет влево?
C
1
0b0010001 -> 0b10001000 // shift 00010001 3 times
(если по теории, что мы сдвигаем весь байт)
Цитата Сообщение от design_m Посмотреть сообщение
https://learnc.info/c/bitwise_operators.html
вот поэтому и хотел прочитать, где это всё связно сказано, чтобы не гадать.

Цитата Сообщение от TRam_ Посмотреть сообщение
вот для этого и используется операция "|=".
вот именно, но я про операцию ИЛИ знаю, я имел в виду именно то, что если у битов есть имена, то значит это имя какой-то переменной, и как можно присвоить переменной, которой соответствует какой-то регистр, определенное значение, так можно и присвоить переменной, которой соответсвует какой-то бит, также определенное значение. (по аналогии с ассемблером - там есть адресуемеые регистры, а в некоторых регистрах есть битовая адресация, и это обозначается тем, что в таких регистрах каждый бит имеет, кроме разряда, свое собственное имя, то есть переменную)
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
28.12.2017, 14:06
Цитата Сообщение от design_m Посмотреть сообщение
а теперь если опять сдвигать 1 из 0 разряда 3 раза
Если бы запись
C++
1
UCSRB |= (1<<RXEN)|( 1<<TXEN);
считалась во время выполнения, то она бы была эквивалентна чему-то наподобие

C++
1
2
3
4
5
6
AL = 1;
AL <<= RXEN;
BL = 1;
BL <<= TXEN;
AL |= BL;
UCSRB |= AL;
Но уже ж говорил, что из-за того что все величины в выражении (1<<RXEN)|( 1<<TXEN) - константы, то все действия, кроме последнего, компилятор посчитает сам, к UCSRB будет применяться не регистр AL или какая-то переменная памяти, а посчитанное компилятором значение этого выражения.

Добавлено через 2 минуты
Если объявить

C++
1
2
3
char RXEN = 4;
char TXEN = 3;
UCSRB |= (1<<RXEN)|( 1<<TXEN);
то конечно компилятор посчитать ничего не сможет, и будут проводиться все действия как в коде выше.
Но у нас же
C++
1
2
#define RXEN  4
#define TXEN 3
1
0 / 0 / 0
Регистрация: 30.06.2015
Сообщений: 209
28.12.2017, 19:42
Теперь почти понятно. так ссылку киньте пожалуйста, где это всё описано?
0
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,538
Записей в блоге: 1
28.12.2017, 22:38
design_m, Сложнее кинуть ссылку, где это не описано
Литература C++
Любая книга по Си. Вообще любая. Я даже удивлён, если ты читал какие-то книги, как можно что-то настолько невнимательно читать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
28.12.2017, 22:38

Программа на побитовые сдвиги
Привет! Выполнить путём сдвига вправо все биты, значение которых равно нулю и влево все биты, значение которых равно единице.Т.е. было...

Не работают побитовые операции с++
Использую Microsoft Visual Studio 2012 Express Этот код компилируется, но в переменную с записывается a&amp;&amp;b: #include...

Побитовые сдвиги
Объясните, почему сдвиг битов влево значит умножению на степень двойки. Пример: 6 &lt;&lt; 1 = 6 * 2; 6 &lt;&lt; 3 = 6 * 8; Также...

Побитовые сдвиги
Где применяются побитовые сдвиги и зачем? Вроде не ассемблер учу а тут такое :О

Побитовые сдвиги
Помогите с задачкой :( сопоставить результаты побитового сдвига на*n*бит влево*m&lt;&lt;n* и целочисленного умножения числа*m*на 2n ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
Алиса нашла кучу ошибок компиляции и запуска в проекте, который без проблем компилировался и запускался)))
anaschu 30.06.2026
Я пока посмеюся, но завтра проверю. А вообще интерсно. Дал алисе файл, в котором точно нет ошибок компиляции и запуска, и попросил их найти. Нашла кучу))) Критические ошибки, мешающие компиляции и. . .
сукцессия 16. Общий обзор, в основном что бы другие ии поняли
anaschu 29.06.2026
# Передаточный документ: модель микоризной сукцессии (для нового чата) Этот документ предназначен для того, чтобы новый чат Claude мог продолжить работу без необходимости заново разбираться в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru