Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2014_2015 / LECT8_new1.pptx
Скачиваний:
13
Добавлен:
27.12.2015
Размер:
1.07 Mб
Скачать

БИТОВЫЕ ПОЛЯ В СТРУКТУРАХ

Язык C++ (С) допускает использование в структурах особого типа полей – битовых полей. Их использование делает возможным доступ к отдельным битам более крупных объектов, например

байтов или слов.

Общий синтаксис описания битового поля: тип [имя ]: ширина; [ ] выделены необязательные элементы.

Битовое поле состоит из некоторого числа бит, специфицированных константным выражением - «ширина». Для битового поля спецификатор типа «тип» должен специфицировать беззнаковый целый тип, а константное выражение должно быть неотрицательной целой величиной. Массивы битовых полей, указатели на битовые поля и функции, возвращающие битовые поля не допускаются, а структуры - можно использовать. Идентификатор «имя» именует битовое поле и является

Пример объявления битовых полей: unsigned color : 4;

unsigned underline : 1;

Содержимое битового поля может описываться как имеющее знак (signed), так и как беззнаковое (unsigned) - эти ключевые слова записываются в поле тип. Каждому полю выделяется точно столько бит, сколько задается в поле ширина. Ссылка на битовое поле выполняется по имени, указываемому в поле имя. Если имя в этом поле опущено, запрошенные биты все равно выделяются, но доступ к ним невозможен > надо учитывать длину машинного слова при работе с битовыми полями.

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

struct names

{

char * P_Family; char * P_Name; char * P_SecName;

};

typedef struct

{

unsigned lymph_ unsigned : 11; //ровняем names Patient; //

int structure:1; //0 // 1

int cell_sructure:3;

2 – кубическая, 3 – цилиндрическая,

4 – полигональная, 5-столбчатые,

6 – веретеновидная, 7 – есть миот. aктивность */ int cell_membrane:1; //0 – тонкая, 1 - грубая

int cell_membrane_state:2; //0 – ровная, 1 - неровная

При ссылке на поле в выражениях по маске

выделяются нужные биты и при необходимости выполняется сдвиг числа вправо.

В результате это число вступает в операцию в соответствии с типом как число со знаком или без него.

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

ВНИМАНИЕ!!! Используйте, только если очень надо экономить место (на диске, в памяти) !!!

Проблем больше, чем преимуществ

Union - объединение (куча) - подобно структуре в том,

что содержат поля различных типов, но помещаемые в одно и то же место памяти, т. е. доступ к одному и тому же месту памяти, но по-разному.

Как и для структур, различают шаблон объединения и переменную, созданную по шаблону.

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

Длиной объединения является максимальная из длин отдельных полей шаблона.

Тип поля может быть любым, в том числе и структурой.

Доступ к полям объединения выполняется через

селектор поля '.', либо ссылка формируется операцией ->, если для доступа используется указатель на объединение.

Разрешается создание массива объединений.

Объединение может инициализироваться только первым описанным полем.

Применения объединений:

доступ к одной и той же области памяти либо как к целому, либо к отдельным частям;

формирование целого из частей, например, far- указателя по известным значениям смещения и сегмента;…..

экономия динамической памяти.

Не всегда переносится на другие компьютеры и платформы: зависит от соглашения о выравнивании в

памяти типов данных объединения

Пример:

union diagnosis

{

char code; int ID;

char *d_name;

}

ОСТОРОЖНО!!!! ИСПОЛЬЗОВАТЬ ТОЛЬК В КРАЙНЕМ СЛУЧАЕ!!!!

Создает новый тип, но не переменную для даль- нейшего использования надо объявить переменную этого типа. Обращение – как к элементам структуры

. . .

diagnosis diag1, dial2; char * s=‘lymph_node’; diag2. d_name=s; diag1.code=‘N’;

. . .

ВАЖНО!!! Следите, какое значение внесли в кучу последним!!! Если далее сразу написать

int ID=diag1.ID, получите бессмысленное значение, а

В С++ есть свой механизм выделения и освобождения памяти — ф-ии new и delete.

Пример :

int * p = new int[1000000]; // память под 1000000 чисел типа int

Т.е. при использовании функции new не нужно приводить указатель и не нужно использовать sizeof(). Освобождение выделенной при помощи new памяти: delete [] p;

Если требуется выделить память под 1 эл-т, то можно: int * q = new int;

или

int * q = new int(10); // выделен. int проинциализируется значением 10

в этом случае удаление будет выглядеть так: delete q;

Выделять динамически небольшие кусочки памяти (например, под 1 эл-т простого типа данных) не целесообразно по 2м причинам:

1. При динамическом выделении памяти в ней помимо значения указанного типа будет храниться служебная информация ОС и С/С++. Таким образом потребуется гораздо больше памяти, чем при хранении необходимых данных на стеке.

2. Если в памяти хранить много маленьких кусочков, то она будет сильно фрагментирована и большой массив данных может не поместиться.

Многомерные массивы. new позволяет выделять только одномерные

массивы для работы с многомерными массивами необходимо

воспринимать их как массив указателей на другие массивы.

Выделение динамической памяти под массив чисел размера n на m.

1ый способ:

на 1 шаге выделяется указатель на массив указателей, а

на 2 шаге, в цикле каждому указателю из этого массива выделяется

массив чисел в памяти. Плох тем, что в нём требуется n+1 выделение

памяти, а это достаточно долгая по времени операция.

int ** a = new int*[n];

 

for (int i = 0; i != n; ++i)

 

a[i] = new int[m];

 

2ой способ:

на 1 шаге выделение массива указателей и массива чисел

размером n на m. На 2 шаге каждому указателю из массива ставится в

соответствие строка в массиве чисел. При этом всего 2 выделения памяти.

int ** a = new int*[n];

 

a[0] = new int[n*m];

 

for (int i = 1; i != n; ++i)

 

a[i] = a[0] + i*m;

 

Для освобождения памяти требуется выполнить:

1ый способ:

 

2ой способ:

for (int i = 0; i != n; ++i)

delete [ ] a[0];

delete [ ] a[i];

 

delete [ ] a;

delete [ ] a;

2ой способ опять же требует меньше вызовов ф-ии delete [ ], чем 1.

Соседние файлы в папке 2014_2015