учебники, программирование, основы, введение в,

 

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

Структуры
Объявление структуры
Структуры языка C++ представляют поименованную совокупность компонентов, называемых полями, или элементами структуры. Элементом структуры может быть:

  • переменная любого допустимого типа;
  • битовое поле;
  • функция.

Объявление структуры имеет следующее формальное описание:
struct [имя_структуры] {
тип_элемента_структуры  имя_ элемента1;
тип_элемента_структуры  имя_ элемента2;
...
тип_элемента_структуры  имя_ элементаN;
} [список_объявляемых_переменных];
Объявление структуры с битовыми полями имеет следующее формальное описание:
struct [имя_структуры] {
тип_элемента_структуры 
[имя_ элемента1] : число_бит;
тип_элемента_структуры 
[имя_ элемента2] : число_бит;
...
тип_элемента_структуры 
[имя_ элементаN] : число_бит;
} [список_объявляемых_переменных];
Возможно неполное объявление структуры, имеющее следующее формальное описание:
struct имя_структуры;
При отсутствии имени объявляемой структуры создается анонимная структура. При создании анонимной структуры обычно указывается список объявляемых переменных.
Список объявляемых переменных типа данной структуры может содержать:

  • имена переменных;
  • имена массивов;
  • указатели.

Например: struct sA {char a[2], int i;} struA, struB[10], *struC;
Для использования указателя на структуру ему необходимо присвоить адрес переменной типа структуры.
Размер структуры с битовыми полями всегда кратен байту. Битовые поля можно определять для целочисленных переменных типа int, unsigned int, char и unsigned char. Одна структура одновременно может содержать и переменные, и битовые поля. Если для битового поля не задано имя элемента, то доступ к такому полю не разрешен, но количество указанных бит в структуре размещается.
Типом элемента структуры может быть:

  • другой структурный тип (допускаются вложенные структуры);
  • указатель на данный структурный тип;
  • неполно объявленный структурный тип;
  • любой другой базовый или производный тип, не ссылающийся рекурсивно на объявляемый структурный тип.

Например:
struct sA {char a[2], sA* this_struct;}; 
// Корректное объявление структуры
struct sB;  
// Неполное объявление структуры
struct sA {char a[2], sB sb*_struct;}; 
// Корректное объявление структуры
struct sA {char a[2], sA this_struct;}; 
// Ошибочное объявление
Структура не может содержать в качестве вложенной структуры саму себя, но она может содержать элемент, являющийся указателем на объявляемую структуру.
Например:
struct structA {
struct structA *pA; int iA; } sA;
// pA указатель на структуру
При одновременном объявлении структурного типа, объявлении переменной данного типа и ее инициализации список значений указывается в фигурных скобках в последовательности, соответствующей последовательности определения элементов структуры.
Например:
struct POINT   // Объявление структурного
// типа POINT
{
int x;      // Объявление элементов x и y
int y;
} p_screen = { 50, 100 };
// Эквивалентно записи p_screen.x = 50;
// и p_screen.y = 100;

http://localhost:3232/img/empty.gifВыделение памяти

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

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

Рассмотрим пример выделения памяти под структуру
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 байта. Элементы структуры будут размещены в памяти в следующем порядке:
Для целочисленных значений, предусматривающих наличие знакового разряда (например, 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);
// Функция возвращает указатель
// на структуру

http://localhost:3232/img/empty.gifОбъединения

Объединение позволяет размещать в одном месте памяти данные, доступ к которым реализуется через переменные разных типов.
Использование объединений значительно экономит память, выделяемую под объекты.
При создании переменной типа объединение память под все элементы объединения выделяется исходя из размера наибольшего его элемента. В каждый отдельный момент времени объединение используется для доступа только к одному элементу данных, входящих в объединение.
Так, компилятор Visual C++ выделит 4 байта под следующее объединение:
union unionA {
char ch1;
float f1;} a1;

Элементы объединения

Количество занимаемых байтов

char ch1

1

float f1

1

2

3

4

Объединения, как и структуры, могут содержать битовые поля.
Инициализировать объединение при его объявлении можно только заданием значения первого элемента объединения.
Например:
union unionA {
char ch1;
float f1;} a1={ 'M' };
Доступ к элементам объединения, аналогично доступу к элементам структур, выполняется с помощью операторов . и ->.
Например:
union TypeNum
{
int    i;
long  l; 
float  f; 
};
union TypeNum vNum = { 1 };
// Инициализация первого элемента объединения i = 1
cout<< vNum.i;
vNum.f = 4.13;
cout<< vNum.f;
Элементы объединения не могут иметь модификаторов доступа и всегда реализуются как общедоступные (public).
Перечисления
Перечисление, или перечислимый тип определяет множество, состоящее из значений, указанных через запятую в фигурных скобках.
Перечисление задает для каждого мнемонического названия в указываемом множестве свой индекс.
Перечисление может иметь следующее формальное описание:
enum имя_типа {список_значений}
список_объявляемых_переменных;
enum имя_типа список_объявляемых_переменных;
enum (список_элемент=значение);
Перечислимый тип описывает множество, состоящее из элементов-констант, иногда называемых нумераторами или именованными константами.
Значение каждого нумератора определяется как значение типа int. По умолчанию первый нумератор определяется значением 0, второй - значением 1 и т.д. Для инициализации значений нумератора не с 0, а с другого целочисленного значения, следует присвоить это значение первому элементу списка значений перечислимого типа.
Например:
// Создание перечисления
enum eDay{sn, mn, ts, wd, th, fr, st} day1;
// переменная day1 будет принимать
// значения в диапазоне от 0 до 6
day1=st;      
// day1 - переменная перечислимого типа
int i1=sn;  
// i1 будет равно 0
day1= eDay(0);     
// eDay(0) равно значению sn
enum(color1=255);       
// Объявление перечисления, определяющего
// именованную целую константу color1
int icolor=color1;
enum eDay2{sn=1, mn, ts, wd, th, fr, st} day2;
// переменная day2 будет принимать
// значения в диапазоне от 1 до 7 
Для перечислимого типа существует понятие диапазона значений, определяемого как диапазон целочисленных значений, которые может принимать переменная данного перечислимого типа.
Для перечислимого типа можно создавать указатели.

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г.Яндекс.Метрика