Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции за I семестр конспект Гуревича для C++ B....doc
Скачиваний:
11
Добавлен:
21.11.2018
Размер:
1.3 Mб
Скачать

11.5. Операция sizeof

Данная операция позволяет определить размер объекта по ID или типу, результатом является размер памяти в байтах (тип результата int). Формат записи:

sizeof(параметр);

где: «параметр» – тип или идентификатор объекта (не ID функции).

Если указан идентификатор сложного объекта (массив, структура, объединение), то получаем размер всего сложного объекта. Например:

sizeof(int)  размер памяти – 2 байта,

int b[5];

sizeof(b)  размер памяти – 10 байт.

При переносе программы с одной платформы на другую нельзя делать предположений, например, о размере типа int, так как для оперативной системы (ОС) MS DOS этот тип имеет размер в два байта, а для ОС Windows 9X – четыре байта. В стандарте языка С поэтому диапазоны значений для основных типов не задаются, а определяются только соотношения между их размерами, например:

sizeof (float) < sizeof (double) < sizeof (long double) ,

sizeof (char) < sizeof (short) < sizeof (int) < sizeof (long) .

11.6. Побитовые логические операции. Операции над битами

В СИ предусмотрен набор операций для работы с отдельными битами слов. Эти операции нельзя применять к переменным вещественного типа (float, double).

Перечень операций над битами и их обозначения:

~ - инвертирование (унарная операция);

& - побитовое И - конъюнкция;

| - побитовое включающее ИЛИ - дизъюнкция;

^ - побитовое исключающее ИЛИ - сложение по модулю 2;

>> - сдвиг вправо;

<< - сдвиг влево.

Пары символов (>>,<<) разделять нельзя.

Общий вид операции инвертирования:

~ <выражение>

Остальные операции над битами имеют вид:

<выражение1> <знак_операции> <выражение2>

Операндами операций над битами могут быть только выражения, приводимые к целому типу. Операнды представляются в двоичной форме, и операции выполняются поразрядно, т.е. над каждым битом (для операций &, |, ^ - над каждой парой соответствующих бит, взятых от первого и второго операндов) (знаковый разряд особо не выделяется).

Операция ~ означает замену значения бита на противоположное (т.е 0 на 1 , а 1 на 0).

Операция & дает 1, если оба участвующих в ней бита равны 1; иначе дает 0.

Операция | дает 1, если хотя бы один из участвующих в ней битов равен 1; иначе дает 0.

Операция ^ дает 1, если один из участвующих в ней битов равен 1, а другой 0; иначе (т.е. если оба бита одинаковы) дает 0.

Примеры:

~0xF0  0x0F

0xFF & 0x0F  0x0F

0xF0 | 0x11  0xF1

0xF4 ^ 0xF5  0x01

Операция & часто используется для маскирования (выделения) некоторого множества битов. Например, оператор w = n & 0177 передает в w семь младших битов n, полагая остальные равными нулю.

Необходимо отличать побитовые операции & и | от логических операций && и ||, которые подразумевают вычисление значения истинности. Если x=1, y=2, то x & y равно нулю, а x && y равно 1.

0x81<<1  0x02

0x81>>1  0x40

Унарная операция (~) дает дополнение к целому. Это означает, что каждый бит со значением 1 получает значение 0 и наоборот. Эта операция обычно оказывается полезной в выражениях типа:

X & (~)077,

где последние 6 битов X маскируются нулем. Это выражение не зависит от длины слова и поэтому предпочтительнее, чем, например:

X & 0177700,

где предполагается, что X занимает 16 битов, такая переносимая форма не требует никаких дополнительных затрат.

Операции сдвига << и >> осуществляют соответственно сдвиг вправо (влево) своего левого операнда, на число битовых позиций, задаваемых правым операндом. Таким образом, x<<2 сдвигает x влево на две позиции, заполняя освобождающиеся биты нулями, что эквивалентно умножению на 4.

Операции сдвига выполняются для всех разрядов с потерей выходящих за границы битов. Если выражение1 имеет тип unsigned, то при сдвиге вправо освобождающиеся разряды гарантированно заполняются нулями (логический сдвиг). Выражения типа signed могут, но не обязательно, сдвигаться вправо с копированием знакового разряда (арифметический сдвиг). При сдвиге влево освобождающиеся разряды всегда заполняются нулями. Выражение2 не должно быть отрицательно.

Операции сдвига вправо на k разрядов весьма эффективны для деления, а сдвиг влево - для умножения целых чисел на 2 в степени k:

x<<1  x*2

x>>1  x/2

x<<3  x*8

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

Двуместные операции над битами (&, |, ^, <<, >>) могут использоваться в сокращенных формах записи операции присваивания:

int i,j,k;

. . .

i |= j  i = i | j - включение в поле i единиц из поля j;

i &= 0xFF  i = i & 0xFF - выделение в поле i единиц по маске поля 0x00FF;

k ^= j - выделение в поле k отличающихся разрядов в полях k и j;

i ^= i - обнуление всех разрядов поля i .

Операции над битами реализуются, как правило, одной машинной командой и рекомендуются для использования во всех подходящих случаях.

В математическом смысле операнды логических операций над битами можно рассматривать как отображение некоторых множеств с размерностью не более разрядности операнда на значения {0,1}.

Пусть единица означает обладание элемента множества некоторым свойством, тогда очевидна теоретико-множественная интерпретация рассма­три­ваемых операций:

~ - дополнение; | - объединение; & - пересечение.

Простейшее применение - проверка нечетности целого числа:

int i;

...

if (i &1) printf(" Значение i нечетно!");

Комбинирование операций над битами с арифметическими операциями часто позволяет упростить выражения. Например, получение размера области в блоках размером 16 байт для размещения объекта размером x байт:

(x + 15)>>4

Другие возможности оперирования над битами:

- использование структур с битовыми полями;

  • доступ к битам как разрядам арифметических данных.