Расположение структурных переменных в памяти
Имена полей одного типа можно перечислить через запятую.
Например:
struct PointRecType
{int x, y;
};
Имена полей в одном шаблоне структуры должны быть уникальными. Однако в разных шаблонах можно использовать совпадающие имена полей. Более того, имя шаблона может совпадать с именами полей и переменных. Поскольку имена полей «скрыты» внутри шаблона, они могут дублировать «внешние» переменные и поля в других описаниях структур.
Например:
structPointRecType //определение шаблона структурыPointRecType
{ int x, y;
};
structColorPointRecType //определение шаблона структурыColorPointRecType
{int x, y;
unsigned color;
};
struct // определение шаблона структурыбез имени
{ PointRecType point;
ColorPointRecType color_point;
} big_struct; // определение структурной переменнойbig_struct
int x, y; //определение простых переменных
PointRecType point; //определение структурной переменной типа PointRecType
ColorPointRecType color_point ; //определение структурной переменной типа ColorPointRecType
Здесь x,
point.x,
color_point.x,
big_struct.point.x,
big_struct.color_point.x – разные значения.
Как мы видим из примера, элементом определяемого структурного типа может быть другая структура, тип которой уже определен. В качестве членов структуры можно объявлять массивы других структур. В отношении полей структурного типа существует только одно существенное ограничение – поле не может иметь тот же тип, что и определяемый структурный тип, однако оно может иметь тип указателя на этот тип.
Например:
struct Book{Book my_s; //error !!!!!
char name[20];
char title[44];
int year;
float price;
};
struct Book{Book & my_s; //error !!!!!
char name[20];
char title[44];
int year;
float price;
};
struct Book{Book *my_s; //OK!!!!!
char name[20];
char title[44];
int year;
float price;
};
Область видимости шаблона структуры:
· локальный шаблон структуры описан внутри блока { }и видим только из пределов данного блока, в частности из пределов конкретной функции;
· если описание шаблона структуры помещено вне блоков, такой шаблон видим во всех функциях ниже точки описания шаблона до границы файла. Нельзя описать шаблон с реквизитом extern.
Изучая структуры, имеет смысл обращать внимание на их представление в памяти компьютера. Порядок описания полей в определении структурного типа задаёт порядок их расположения в памяти.
Рассмотрим структуру:
struct {
long L;
int i1, i2;
char c[4];
} STR1;
В памяти каждый элемент имеет свое место, и размещаются они последовательно:
f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
long L int i1 int i2 char c[4]
Компилятор выделяет под структурную переменную STR1 число байтов памяти, достаточное для хранения всех ее полей. Однако выделенное количество байт не всегда равно сумме длин отдельных полейиз-за влияния дополнительного фактора внутреннего представления структурных переменных,называемоговыравниванием.
При выравнивании на границе байта отдельные поля структурной переменной в памяти располагаются без зазоров, с любого четного или нечетного адреса; размер занимаемой структурной переменной памяти равен сумме размеров полей шаблона структуры.
Выравнивание на границе байта устанавливает директива препроцессора
#pragma pack(push,n); аргумент n задает выравнивание данных в структурах на n байт (n=(1,2,4,8,16) ). Отмена директивы: #pragma pack(pop). Директива #pragma pack(show) выводит в качестве warning значение выравнивания по умолчанию, например: value of pragma pack(show) == 8.
При выравнивании на границе слова компилятор при размещении структурной переменной в памяти может вставлять между полями пустые байты для того, чтобы соблюдались следующие правила:
· отдельная структурная переменная (элемент массива структурных переменных) начинается на границе слова;
· любое поле, тип которого не совпадает с типом char, будет начинаться на границе слова;
· при необходимости в конце структурной переменной добавляются байты.
Расположение в памяти структурной переменной STR2при наличии выравнивания на границе 4 –х байт:
struct {
long L;
char c[3];
int i1, i2;
} STR2;
f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
long L char c[3] int i1 int i2
Сумма размеров элементов структуры (4+3+4+4=15) меньше, чем отведено структуре в целом (16) из-за того, что размер массива char c[3]; не кратен длине слова компьютера и перед элементом int i1 для выравнивания вставлен пустой байт.
Выделенное число байт возвращает операция sizeof .