Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
В листинге 15.4 объединение Views применяется для сравнения подходов на основе битовых полей и побитовых операций. Здесь box — это объединение Views, поэтому box. st_view представляет собой структуру box props, использующую битовые поля, a box.ui view — те же самые данные, но представленные как значение
unsigned short.
648 Глава 15
Рис. 15.3. Объединение как целое число и как структура
Вспомните, что объединение может иметь инициализированный первый член, поэтому установленные значения соответствуют представлению структуры. Программа отображает свойства окна с помощью функции, основанной на представлении структуры, и также посредством функции, основанной на представлении unsigned short. Любой из подходов обеспечивает доступ к данным, но по-разному. Вдобавок в программе применяется определенная ранее в главе функция itobs(), которая позволяет отобразить данные в виде строки двоичных цифр, чтобы можно было видеть, какие биты включены, а какие выключены.
Листинг 15.4. Программа dual view. с
Манипулирование битами 649
Ниже приведен вывод.
Исходные настройки окна: Окно непрозрачно.
Цвет фона желтый.
Рамка отображается.
Цвет рамки зеленый.
Стиль рамки штриховой.
Манипулирование битами 651
Настройки окна с использованием представления unsigned short:
Окно непрозрачно.
Цвет фона желтый.
Рамка отображается.
Стиль рамки штриховой.
Цвет рамки зеленый.
Комбинация битов 00000000000000000010010100000111
Измененные настройки окна:
Окно прозрачно.
Цвет фона голубой.
Рамка отображается.
Цвет рамки желтый.
Стиль рамки пунктирный.
Настройки окна с использованием представления unsigned short:
Окно прозрачно.
Цвет фона голубой.
Рамка не отображается.
Стиль рамки пунктирный.
Цвет рамки желтый.
Комбинация битов 00000000000000000001011100001100
В коде есть несколько моментов, которые необходимо обсудить. Одно из отличий между этими двумя представлениями состоит в том, что побитовому представлению нужна информация о позициях. Например, для представления синего цвета в программе используется константа BLUE, имеющая числовое значение 4. Но поскольку данные организованы в структуре, на самом деле хранить настройку синего цвета для фона будет бит 3 (не забывайте, что нумерация начинается с нуля (см. рис. 15.1)), а настройку синего цвета для рамки — бит 11. Таким образом, в программе определен ряд новых констант:
#define FILL_BLUE 0x8
#define BORDER_BLUE 0x800
Здесь 0x8 — это значение, когда в 1 установлен только бит 3, а 0x800 — значение, когда в 1 установлен только бит 11. Первую константу можно применять при установке бита синего цвета для фона окна, а вторую — при установке бита синего цвета для рамки. Шестнадцатеричная запись упрощает выяснение, какие биты задействованы. Вспомните, что каждая шестнадцатеричная цифра представляет четыре бита. Следовательно, значение 0x800 соответствует комбинации битов 0x8, но с дописанными восемью битами с состоянием 0. Глядя на десятичные эквиваленты, 2048 и 8, заметить такую связь гораздо труднее.
Если значения являются степенями 2, можно воспользоваться операцией сдвига влево. Например, последние две директивы #define можно заменить следующим образом:
#define FILL_BLUE 1<<3
#def ine BORDER_BLUE 1<<11
Во втором операнде указана степень для возведения числа 2. Так, значение 0x8 равно 2 s, а значение 0x800 — 2 И. Аналогично, выражение 1<<<11 являются константными и вычисляются на этапе компиляции.
Вместо директивы #define для создания символических констант можно применять перечисление.
652 Глава 15
Например, можно поступить так:
enum { OPAQUE = 0xl, FILL_BLUE = 0x8, FILL_GREEN = 0x4, FILL_RED = 0x2, FILL_MASK = 0xE, BORDER = 0x100, BORDER_BLUE = 0x800,
BORDER_GREEN = 0x400, BORDER_RED = 0x200, BORDER_MASK = 0xEOO,
B_DOTTED = 0x1000, B_DASHED = 0x2000, STYLE_MASK = 0x3000 };
Если вы не намерены создавать переменные с типом этого перечисления, указывать имя в объявлении не обязательно.
Обратите внимание, что использовать побитовые операции для изменения настроек сложнее. В качестве примера давайте установим голубой цвет для фона окна. В данном случае недостаточно просто включить биты, соответствующие синему и зеленому цветам:
box.us_view |= (FILL_BLUE | FILL_GREEN); /* сбросить фон */
Дело в том, что цвет также полагается на настройку бита, отвечающего за красный цвет. Если этот бит был включен ранее (скажем, для получения желтого цвета), то приведенный код оставит бит красного цвета установленным и установит в 1 биты синего и зеленого цветов, давая в результате белый цвет. Обойти эту проблему проще всего, сначала отключив все биты, отвечающие за цвет, и лишь затем устанавливать новые значения. Именно поэтому в программе содержится следующий код:
box.us_view &= ~FILL_MASK; /* очистить биты фона */
box.us_view |= (FILL_BLUE | FILL_GREEN); /* переустановить фон */
Для демонстрации того, что может произойти, если предварительно не очистить соответствующие биты, в программе также предусмотрена такая строка:
box.us_view |= BORDER_RED; /* ошибочный подход */
Из-за того, что бит BORDER_GREEN уже был установлен, результирующим цветом будет BORDER_GREEN | BORDER_RED, что соответствует желтому цвету.
В си туациях подобного рода применять битовые поля проще:
box . st view.hll_color = CYAN; /* эквивалент с битовым полем */
Тогда нет нужды в предварительной очистке битов. Кроме того, члены битовых полей допускают использование одних и тех же значений цвета для рамки и фона окна. В случае подхода с побитовыми операциями придется применять отличающиеся значения (значения, отражающие действительные позиции битов).
Далее, сравните следующие два оператора вывода:
printf("Цвет рамки %s.\n", colors[pb->border_color]);
printf("Цвет рамки %s.\n", colors!(us >> 9) & 07]);
В первом операторе выражение pb->border_color имеет значение из диапазона 0-7, поэтому его можно использовать как индекс в массиве colors. Получить ту же информацию с помощью побитовых операций сложнее. Один из подходов предусматривает применение ui >> 9 для сдвига битов цвета рамки в самую правую позицию (биты 0-2) с последующим объединением полученного значения с маской 07, в результате чего все биты кроме трех самых правых будут отключены. То, что осталось, будет находиться в диапазоне 0-7 и может использоваться в качестве индекса для массива colors.
Манипулирование битами 653
Внимание!
Соответствие между битовыми полями и позициями битов зависит от реализации. Например, при выполнении программы из листинга 15.4 в старой системе Macintosh PowerPC получается следующий вывод:
Читать дальшеИнтервал:
Закладка: