Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ЭУМКД КИТ-ч1-Бутов.docx
Скачиваний:
9
Добавлен:
05.05.2019
Размер:
262.85 Кб
Скачать

Битовые поля

Битовые поля – это особый вид полей структуры. Они используются для плотной упаковки данных, например, флажков типа «да/нет». Это объясняется тем, что минимальная адресуемая ячейка оперативной памяти имеет длину один байт (8 бит), в то время как для хранения флажка достаточно одного бита. При описании битового поля после имени через двоеточие указывается длина поля в битах. Битовые поля могут быть любого целого типа и обычно используется тип unsigned int (сокращенно unsigned) . Например:

struct options

{

unsigned bold : 1;

unsigned italic : 1;

unsigned underline : 1;

unsigned background : 4;

} opt;

Под переменную opt структурного типа options будет отведена память размером 1 байт (если не использовать битовые поля, то структурная переменная будет занимать минимум 4 байта).

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

Объединения

Объединение представляет собой частный случай структуры, все поля которой располагаются по одному и тому же адресу. Формат описания такой же, как и у структуры, только вместо ключевого слова struct используется слово union. Длина объединения равна наибольшей из длин его полей. В каждый момент времени объединение хранит только одно значение, и ответственность за его правильное использование лежит на программисте.

Объединения применяют для экономии памяти в тех случаях, когда известно, что больше одного поля одновременно не требуется. Пример:

#include <stdio.h>

void main()

{

int payType; //тип платежа

union payment

{

char card[25]; //оплата по карте

int check; //оплата чеком

} info;

// . . . присваивание значений переменным payType и info

switch (payType)

{

case 0: printf("Оплата по карте: %s", info.card); break;

case 1: printf("Оплата чеком: %d", info.check); break;

}

}

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

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

#include <stdio.h>

void main()

{

struct

{

int payType;

union

{

char card[25];

int check;

};

} info;

// . . . присваивание значения переменной info

switch (info.payType)

{

case 0: printf("Оплата по карте: %s", info.card); break;

case 1: printf("Оплата чеком: %d", info.check); break;

}

}

Перечисления

Перечисление – это список именованных целых констант. Для описания перечисления используется следующий формат:

enum [имяПеречисления] {списокИменованныхКонстант};

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

enum boolean {NO, YES}; // NO = 0, YES = 1

boolean bool; //описали переменную bool типа boolean

bool = YES; //bool = 1

enum months {JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};

months mon; // FEB=2, MAR=3, APR=4, . . . , DEC=12

mon = DEC; //mon = 12

enum controls {BELL=’\a’, BACKSPACE=’\b’, NEWLINE=’\n’, TAB=’\t’, VTAB=’\v’};

char ch;

while(1)

{

if ((ch = getchar()) == NEWLINE) break;

. . .

}

Пример формирования на экране меню

#include <stdio.h>

void main()

{

enum menu {READ=1, WRITE, APPEND, EXIT};

int num;

do

{

printf("1. Читать\n");

printf("2. Писать\n");

printf("3. Дописать в конец\n");

printf("4. Выйти\n");

printf("\nВаш выбор?\n");

scanf("%d", &num);

if (num == EXIT) break;

switch (num)

{

case READ: . . . ; break;

case WRITE: . . . ; break;

case APPEND: . . . ; break;

default: printf("Неверный ввод\n"); break;

}

} while(1);

}

Переименование типов

Для того, чтобы сделать программу более ясной, можно дать типу новое имя с помощью ключевого слова typedef:

typedef Тип НовоеИмяТипа[Размерность];

Размерность может отсутствовать. Примеры:

typedef unsigned int uint;

typedef char message[100];

typedef char * string;

Введенные таким образом имена можно использовать таким же образом, как и имена простых типов данных:

uint i, j ; //две переменные типа unsigned int

message str[10]; //массив из 10 строк по 100 символов в каждой строке

string p = str; //инициализированный указатель на char

Кроме задания типам с длинными описаниями более коротких имен, typedef используется для облегчения переносимости программ: если машинно-зависимые типы объявить с помощью операторов typedef, при переносе программы потребуется внести изменения только в эти операторы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]