- •БИТОВЫЕ ПОЛЯ В СТРУКТУРАХ
- •Пример объявления битовых полей: unsigned color : 4;
- •struct names
- •При ссылке на поле в выражениях по маске
- •Union - объединение (куча) - подобно структуре в том,
- •Доступ к полям объединения выполняется через
- •Пример:
- •Многомерные массивы. new позволяет выделять только одномерные
- •УТЕЧКА
- •Утечки памяти потребление памяти программой
- •РАБОТА СО СТРОКАМИ
- •Прототип функции strcpy:
- •char* strdup(const char *source);
- •Пример:
- •Пример:
- •Сравнение строк
- •Пример:
- •Ф-я strncmp выполняет сравнение заданного
- •Функция strnicmp выполняет сравнение заданного
- •ПРЕОБРАЗОВАНИЕ СТРОК
- •ОБРАЩЕНИЕ СТРОК
- •Ф-я strchr определяет первое вхождение символа с в
- •Пример:
- •Ф-я strcspn просматривает строку str1 и выдает длину
БИТОВЫЕ ПОЛЯ В СТРУКТУРАХ
Язык 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.