Объединения

Размещение структурных переменных в памяти

Массивы структур

Структурный тип "struct ID_структуры", как правило, используют для декларации массивов, элементами которых являются структурные переменные. Это позволяет создавать программы, оперирующие с "примитивными базами данных". Например:

struct person spisok[100]; // spisok - массив структур

Или можно записать так:

struct person {

char fio[40];

int day, month, year;

} spisok[100];

В данном случае обращение к полю day i-той записи может быть выполнено, например, так:

spisok[i].day=22;

 

Элементы структур в общем случае размещаются в памяти последо­ва­тельно с учетом выравнивания начальных адресов полей.

Выравнивание (align) означает, что компилятор выбирает адреса переменных (в т.ч. полей структуры) так, чтобы они были кратны некоторой величине. Эта величина определяется типом переменной и особенностями адресации данных этого типа на аппаратном уровне (чаще всего она равна 2). Часто выравнивание не обязательно, но при этом скорость обращения к объекту может снижаться. Если выравнивание производится, компилятор может быть вынужден добавить между полями структуры пустые байты, и тогда размер структуры (определяемый с помощью sizeof) будет превышать сумму размеров ее полей.

 

.

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

Объединенный тип данных декларируется подобно структурному типу:

union ID_объединения {

описание полей

};

Пример описания объединенного типа:

union word {

int nom;

char str[20];

};

Пример объявления объектов объединенного типа:

union word p_w, mas_w[100];

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

Например, поток сообщений по каналу связи пусть содержит сообще­ния трех видов:

struct m1 {

char code;

float data[100]; };

struct m2 {

char code;

int mode; };

struct m3 {

char code, note[80]; };

Элемент code - признак вида сообщения. Удобно описать буфер (место для хранения) сообщений в виде

struct m123 {

char code;

union {

float data[100];

int mode;

char note[80]; };

};

Практически все вышесказанное для структур имеет место и для объединений.

Декларация данных типа union, создание переменных этого типа и обращение к полям объединений производится аналогично структурам.

Пример использования переменных типа union:

. . .

union W {

int a;

float b;

char s[5];

};

void main(void) {

W s;

s.a = 4;

printf(“\n Integer a = %d, Sizeof(s.a) = %d”, s.a, sizeof(s.a));

s.b = 1.5;

printf(“\n Float b = %f, Sizeof(s.b) = %d”, s.b, sizeof(s.b));

strcpy(s.s, “Minsk”);

printf(“\n Char[] a = %s, Sizeof(s.s) = %d”, s.s, sizeof(s.s));

printf(“\n Sizeof(s) = %d”, sizeof(s));

getch();

}

Результат работы программы:

Integer a = 4, Sizeof(s.a) = 2

Float b = 1.500000, Sizeof(s.b) = 4

Char[] a = Minsk, Sizeof(s.s) = 5

Sizeof(s) = 5

 

 

16. Файлы в языке С

 

Файл – это набор данных, размещенный на внешнем носителе и рассматриваемый в процессе обработки и пересылки как единое целое. В файлах размещаются данные, предназначенные для длительного хранения.

В языке Си имеется большой набор функций для работы с файлами, большинство которых находятся в библиотеках stdio.h и io.h. Все они рассматривают файл как последовательность байт, из которой можно читать или в которую можно записывать данные различными способами. При работе с файлом (при открытии файла) создается указатель позиции в файле (аналогичный по назначению курсору на экране) - он указывает, в каком месте файла будет производиться чтение/запись. По мере выполнения операций чтения/записи этот указатель автоматически продвигается вперед, так что каждая последующая операция чтения/записи будет читать/записывать уже следующую информацию. Указатель можно также непосредственно устанавливать в нужную позицию.