Опубликован: 01.11.2004 | Уровень: для всех | Доступ: свободно | ВУЗ: Московский государственный университет имени М.В.Ломоносова
Лекция 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 ), старший левый бит из общего числа битов, выделяемых под данное битовое поле, интерпретируется как знак. Например, битовое значение 1 для поля 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 >
Александр Демьяненко
Александр Демьяненко

Можно ли сдавать один и тот же тест несколько раз?
Или же один и тот же тест можно сдать лишь однажды?

Максим Стогний
Максим Стогний

Добрый день!

Скажите, пожалуйста, если в терминологии объектно-ориентированного программирования функции также называются методами или методами - членами класса, в примере объявления указателя на метод использовали в формальном описании оба названия:

тип_метода (имя_класса::*имя_метода_указателя)
    (список параметров);
тип_функции (*имя_ функции_указателя)
    (список параметров);

при этом можно было  тип_функции во втором описании заменить на тип_метода? Т.е.:

тип_метода (*имя_ метода_указателя)
    (список параметров);