Московский государственный университет имени М.В.Ломоносова
Опубликован: 03.10.2006 | Доступ: свободный | Студентов: 1224 / 79 | Длительность: 09:08:00
Специальности: Программист
Лекция 8:

Производные типы данных языка C++. Структуры, объединения и перечисления

< Лекция 7 || Лекция 8: 123 || Лекция 9 >

Выделение памяти

При создании переменной типа структуры:

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

Рассмотрим пример выделения памяти под структуру

struct structA { 
    char cA; 
    char sA[2]; 
    float fA;};

При создании переменной структурного типа:

structA s1;

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

char cA char sA[2] float fA
1 2 3 4 5 6 7

Рассмотрим пример выделения памяти под структуру

struct structB { 
    int i1:2; 
    int i2:3; 
    int :6; 
    unsigned int i3:4;};

При создании переменной структурного типа:

structB s2;

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


Рис. 8.1.

Для целочисленных значений, предусматривающих наличие знакового разряда (например, int ), старший левый бит из общего числа битов, выделяемых под данное битовое поле, интерпретируется как знак. Например, битовое значение 11 для поля i1 будет восприниматься как -1, а значение 11 для поля i3 - как 3.

Доступ к элементам структуры

Элементы структуры могут иметь модификаторы доступа: public, private и protected. По умолчанию все элементы структуры объявляются как общедоступные ( public ). Забегая вперед, следует сказать, что все члены класса по умолчанию объявляются как защищенные ( private ).

Для обращения к отдельным элементам структуры используются операторы: . и ->.

Доступ к элементам структуры может иметь следующее формальное описание:

переменная_структурного_типа.элемент_структуры=значение;
имя_структурного_типа *указатель_структуры=
    & переменная_структурного_типа;
указатель_структуры->элемент_структуры=значение;

Например:

struct structA { 
  char c1; 
  char s1[4]; 
  float f1;} aS1,    
    // aS1 - переменная структурного типа
  *prtaS1=&aS1;    
    // prtaS1 - указатель на структуру aS1
struct structB {
  struct structA aS2;    
    // Вложенная структура
} bS1,*prtbS1=&bS1;
aS1.c1= 'Е';        
    // Доступ к элементу c1 структуры aS1
prtaS1->c1= 'Е';     
    // Доступ к элементу c1 через 
    // указатель prtaS1
(*prtaS1).c1= 'Е';    
    // Доступ к элементу c1 
(prtbS1->aS2).c1='Е'; 
    // Доступ к элементу вложенной структуры

Доступ к элементу массива структурного типа имеет следующий формальный синтаксис:

имя_массива[индекс_элемента_массива].элемент_структуры

При использовании указателей на массив структур следует сначала присвоить указателю адрес первого элемента массива, а затем реализовывать доступ к элементам массива, изменяя этот указатель адреса.

Например:

struct structA { 
    int i; char c;} sA[4], *psA;
psA=&sA[0]; 
…
cout<<psA->i;    
  // Доступ к первому элементу массива 
  // структур
  // Переход ко второму элементу массива
psA++;        
  // Эквивалентно записи:  psA=&sA[1];
cout<<psA->i;

Передача структур в качестве параметров

Переменные структурного типа и элементы структуры можно передавать в функции в качестве параметров.

Передача параметров может выполняться:

  • по ссылке или указателю;
  • по значению.

При передаче параметра по указателю передается только указатель на структуру, при передаче по значению в стек копируется все содержание структуры.

Например:

struct structA { 
    int i; char c;} sA, *psA=&sA;
void F1(struct structA sA);    
    // Передача параметров по значению
void F2(struct structA *psA);    
    // Передача параметров по указателю
void F3(struct structA &sA);
    // Передача параметров по ссылке
…
void F2(struct structA *psA) {
    psA->i =10; }     
    // Доступ к элементу структуры

При большой вложенности вызовов и использовании большого числа структур или их значительных размерах вызов по значению может привести к переполнению стека.

Функция может возвращать значение структурного типа или типа указателя на структуру.

Например:

struct structA { int i; char с;};
struct structA Function3(void);    
    // Функция возвращает значение 
    // структурного типа
struct structA *Function4(void); 
    // Функция возвращает указатель 
    // на структуру
< Лекция 7 || Лекция 8: 123 || Лекция 9 >