Сдвиг вправо (››)
Задача данного оператора cдвинуть биты своего операнда на какое-то количество вправо, начиная со старшего левого бита. Сдвиг вправо числа типа unsigned всегда заполняет освободившиеся биты нулями. Сдвиг вправо числа со знаком в некоторых системах приводи к заполнению этих битов значениями знакового бита, а в других нулями. Все младшие биты будут утеряны.
Операция : 0101 ›› 2 |
Разряд 4 |
Разряд 3 |
Разряд 2 |
Разряд 1 |
Операнд |
0 |
1 |
0 |
1 |
Результат |
0 |
0 |
0 |
1 |
Как видно из таблицы, все биты сместились в право на 2 позиции, единица которая изначально была в 1 разряде вышла за границы и была утеряна. И так в результате применения операции 0101 ›› 2 будет 0001.
Ну что же, теперь думаю Вам стало более понятно что такое побитовые операторы и ка кони работают, в следующей статье я попробую привести ряд общих примеров какую фактическую пользу могут принести подобные операторы.
17. Выравнивание и размер структуры
Есть у нас, допустим структура.
struct my_struct{ int a; char b; int c; }; |
Но если на разных платформах ( например avr и arm ) выполнить следующий код
printf("размер структуры %u\r\n", sizeof( struct my_struct ) ); |
то мы получим разные результаты. Для arm размер структуры равен 12, а для avrравен 5. Почему?
На первый взгляд, потому, что переменные типа int на различных платформах имеют разную разрядность. Для arm это 4 байта, для avr 2 байта.
Перепишем нашу структуру.
struct my_struct{ short a; char b; short c; }; |
Тип short имеет размер 2 байта на всех платформах.
Но мы опять получаем разный размер структуры, для arm 6 байт, для avr 5 байт.
Дело в том что компилятор gcc (да и большинство других) по умолчанию выравнивает поля структуры (дополняет неиспользуемыми байтами) в соответствии с следующим правилом: каждое поле выравнивается по адресу, кратному размеру данного поля. Поле типа int на 32-битной системе будет выровнено по границе 4 байт, short по границе 2 байта. Поля типа char не выравниваются. Размер структуры выравнивается до размера, кратному размеру его максимального элемента.
Но как нам быть, если мы хотим передать структуру с одной платформы на другую.
Устранить поведение по умолчанию и убрать выравнивание можно если указать атрибут packed при описании структуры, директива компилятора #pragma pack(1) также может использоваться для этой цели
struct my_struct{ short a; char b; short c; }__attribute__((__packed__ )); |
В этом случае «пустоты», связанные с выравниванием, исчезают и размер структуры на разных платформах становиться одинаковым.
Если у нас много экземпляров структуры, то отключив выравнивание можно сэкономить память. Отрицательной стороной отключения выравнивания является то, что при этом увеличивается программный код и время необходимые для обработки структур.
