Форум программистов, компьютерный форум CyberForum.ru

Операции сдвига - C++

Восстановить пароль Регистрация
 
BESSON_off
 Аватар для BESSON_off
3 / 0 / 1
Регистрация: 08.07.2013
Сообщений: 329
24.11.2014, 13:51     Операции сдвига #1
Через операторы сдвига можно в одну переменную поместить несколько значений.
C++
1
2
3
4
5
6
int A = 0;
int b[3] = {44,45,46};
A = (int)(b[1]|b[2]<<4|b[1]<<8);
for (int i=0;i<3;i++) {
    b[i] = 0;
}
А как вытащить обратно эти значения в переменные b?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.11.2014, 13:51     Операции сдвига
Посмотрите здесь:

C++ операции сдвига
C++ регистр сдвига????
C++ Операции сдвига, перегруженые функции. Объясните суть
C++ Операции сдвига
Операции сдвига в языке C. C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
24.11.2014, 14:03     Операции сдвига #2
Регистрация: 08.07.2013
Сообщений: 265
и до сих пор не разобрался со сдвигом?

Цитата Сообщение от BESSON_off Посмотреть сообщение
можно в одну переменную поместить несколько значений
А про битовые поля ты что-нибудь слышал?
C
1
2
3
4
5
struct multiBit{
  unsigned a:4;//4х битное поле
  unsigned b:3;//3х битное поле  
  unsigned c:1;//1х битное поле  
};
А про юнионы?
C
1
2
3
4
5
6
7
8
9
union multiValue{
  struct{
    unsigned char a;//1й байт
    unsigned char b;//2й байт
    unsigned char c;//3й байт
    unsigned char d;//4й байт
  }bytes;
  int value;  
};
А теперь то и другое вместе?
C
1
2
3
4
5
6
7
8
union multiBitValue{
  struct{
  unsigned a:4;//4х битное поле
  unsigned b:3;//3х битное поле  
  unsigned c:1;//1х битное поле  
  }bytes;
  int value;  
};
...правда, тут ещё выравнивание желательно через #pragma pack сделать...
BESSON_off
 Аватар для BESSON_off
3 / 0 / 1
Регистрация: 08.07.2013
Сообщений: 329
25.11.2014, 05:23  [ТС]     Операции сдвига #3
Про битовые поля то я слышал, просто макрос RGB привел к тому, что пришлось задуматься, как можно реализовать обратный манёвр.
TheCalligrapher
С чаем беда...
Эксперт С++
 Аватар для TheCalligrapher
2781 / 1427 / 393
Регистрация: 18.10.2014
Сообщений: 2,620
25.11.2014, 06:08     Операции сдвига #4
Цитата Сообщение от BESSON_off Посмотреть сообщение
A = (int)(b[1]|b[2]<<4|b[1]<<8);
Во-первых, битовые операции лучше производить над беззнаковыми типами.

Во-вторых, непонятно, почему 'b[1]' использовано два раза, а 'b[0]' - ни разу.

Цитата Сообщение от BESSON_off Посмотреть сообщение
как можно реализовать обратный манёвр
Если

C++
1
A =  b[0] | b[1] << 4 | b[2] << 8;
то

C++
1
2
3
b[0] = A & 0xF; 
b[1] = A >> 4 & 0xF; 
b[2] = A >> 8 & 0xF;
или

C++
1
2
3
b[0] = A & 0xF; A >>= 4;
b[1] = A & 0xF; A >>= 4;
b[2] = A & 0xF; A >>= 4;
BESSON_off
 Аватар для BESSON_off
3 / 0 / 1
Регистрация: 08.07.2013
Сообщений: 329
26.11.2014, 05:40  [ТС]     Операции сдвига #5
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Во-вторых, непонятно, почему 'b[1]' использовано два раза, а 'b[0]' - ни разу.
Торопился вопрос задать.
За ответ спасибо!
ValeryS
Модератор
6373 / 4839 / 440
Регистрация: 14.02.2011
Сообщений: 16,038
26.11.2014, 06:35     Операции сдвига #6
Цитата Сообщение от BESSON_off Посмотреть сообщение
A = (int)(b[1]|b[2]<<4|b[1]<<8);
Цитата Сообщение от BESSON_off Посмотреть сообщение
просто макрос RGB привел к тому, что пришлось задуматься,
а ты уверен что привел макрос RGB?
Там байты используются
соответственно
C++
1
2
3
4
5
unsigned int color=(unsigned int)(R|G<<8|B<<16);
 
unsigned char R= color&0xFF;
unsigned char G= (color>>8)&0xFF;
unsigned char B= (color>>16)&0xFF;
&0xFF можно не делать, само сделается из-за разной размерности типов
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
26.11.2014, 07:03     Операции сдвига #7
Kuzia domovenok, при чём здесь это? Он сдвигами хотел.BESSON_off, когда ты помещаешь значения в переменную сдвигом, то каждое помещаешь на какие то биты. На какие? Предположим, ты собрал двойное слово из байтов:
C++
1
b=((DWORD)x1)|(((DWORD)x2)<<8)|(((DWORD)x3)<<16)|(((DWORD)x4)<<24);
, а потом хочешь вытащить эти байты. На каких битах они находятся? x1 от нулевого до седьмого, так как всего бит в байте 8, а младший бит всегда и везде нулевой. Младший бит значения нулевой, младший бит значения, упакованного в переменную нулевой, позиция одна, двигать не надо, только маска:
C++
1
x=(char)(b&0x000000FF);
. x2 от 8-го до 15-го, а надо от нулевого до седьмого, разница 8. Обратил внимание на то, что она совпадает с величиной сдвига при помещении? Это не случайно. Значит двигать надо в обратную сторону на те же 8, но помещение мог реализовать кто то другой, а тебе сказать только номера бит, тогда считай разность, она равна меньшему номеру (вычитание ноля даёт разность, равную уменьшаемому).
C++
1
x2=(char)((b&0x0000FF00)>>8);
. x3 от 16-го до 23-го, разность 16,
C++
1
x3=(char)((b&0x00FF0000)>>16);
. x4 от 24-го до 31-го, разность 24.
C++
1
x4=(char)((b&0xFF000000)>>16);
. 0x000000FF, 0x0000FF00, 0x00FF0000 и 0xFF000000 - это маски значений. Как их определять? Есть номера битов, которые тебе нужны, пиши двоичное число, в котором биты с этими номерами равны 1, остальные 0, например, 00000000000000001111111100000000 для битов от 8-го до 15-го. Почему именно здесь единицы? Потому что биты нумеруются слева на право с ноля с увеличением на 1:
биты:0000000000000000111
номера битов:31302928272625242322212019181716151413
. Видишь, где единицы? Теперь группируй биты по четыре:
полубайты:00000000000000001111111100000000
на каких они номерах битов:28-3124-2720-2316-1912-158-114-70-3
. Полученные полубайты заменяй на шестнадцатеричные цифры (такая цифра - это тоже полубайт, но в другой системе счисления) по таблице:
двоичный полубайтшестнадцатеричный полубайт
00000
00011
00102
00113
01004
01015
01106
01117
10008
10019
1010A
1011B
1100C
1101D
1110E
1111F
, получается 0000FF00, теперь в начало пиши 0x. Всё, маска готова. При помещении тоже может понадобиться маска, если исходные значения были представлены типами большей разрядности, чем нужно. Какие биты они на самом деле имеют? Составляй маску по аналогии, например, если ты собираещь двойное слово из ASCII, то маска значения 0x7F, при расширении до двойного слова она становится 0x0000007F, тогда
C++
1
b=(((DWORD)x1)&0x0000007F)|((((DWORD)x2)&0x0000007F)<<7)|((((DWORD)x3)&0x0000007F)<<14)|((((DWORD)x4)&0x0000007F)<<21);
, а маски при выделении значений 0x0000007F, 0x00003F80, 0x001FC000 и 0x0FE00000.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
26.11.2014, 07:06     Операции сдвига #8
Двоичная маска не вся вошла, вот её скрин из экзела:
Операции сдвига
.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.11.2014, 07:09     Операции сдвига
Еще ссылки по теме:

операция сдвига C++
Побитовые операции сдвига C++
C++ Упаковка пакета с помощью операции сдвига

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

Или воспользуйтесь поиском по форуму:
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
26.11.2014, 07:09     Операции сдвига #9
Цитата Сообщение от ValeryS Посмотреть сообщение
&0xFF можно не делать, само сделается из-за разной размерности типов
В принципе да. Когда приводишь к типу, имеющему ту же разрядность, что и помещаемое в него значение, то маска не обязательна.
Yandex
Объявления
26.11.2014, 07:09     Операции сдвига
Ответ Создать тему
Опции темы

Текущее время: 14:42. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru