Типы struct, union и enum в C++

Помимо стандартных типов программист, в языке программирования С++, может создавать свои собственные составные типы данных под названием структуры.

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

Общее описание структуры:

struct [type]
{
	field first;
	...
 
}; var1[,var2[,var3...]]];
Если не указан [type] обязательно должны быть объявлены переменные.

Задача 1 - Написать функцию, которая считает размер конкретной структуры

Создать структуру ФИО и дней рождения. Написать функцию, которая считает размер конкретной структуры.

#include <stdlib.h>
#include <iostream>
#include <cstring>
/*
Создать структуру ФИО и дней рождения. Написать функцию, которая считает размер конкретной структуры. 
*/
using namespace std;
 
	struct Person
	{
		char *f;
		char *i;
		char *o;
		int bd;
	};
 
int countb(Person *p2){
return sizeof(p2->bd)+strlen(p2->f)+strlen(p2->o)+strlen(p2->i);
}
 
int main() {
 
	Person p1;
 
	char f1[]= "Ivanov";
	int SIZEf=strlen(f1)+1;
	p1.f = new char[SIZEf];
	strcpy(p1.f,f1);
	cout<<p1.f<<"\n\n";
 
	char i1[]= "Ivan";
	int SIZEi=strlen(i1)+1;
	p1.i = new char[SIZEi];
	strcpy(p1.i,i1);
	cout<<p1.i<<"\n\n";
 
	char o1[]= "Ivanovich";
	int SIZEo=strlen(o1)+1;
	p1.o = new char[SIZEo];
	strcpy(p1.o,o1);
	cout<<p1.o<<"\n\n";
 
	p1.bd = 12021977;
 
	cout<<"SIZE Person: "<<countb(&p1)<<"\n";
	//cout<<sizeof(Person)<<"\n\n";
	//cout<<sizeof(p1)<<"\n";
	//cout<<sizeof(p1.f)<<"\n";
 
 
	delete [] p1.f;
 
	delete [] p1.i;
 
	delete [] p1.o;
 
 
    return (EXIT_SUCCESS);
}

Действия над структурами

Операции, которые допустимо производить над структурами.

  • Доступ к элементу структуры с помощью операции "." (точка).
  • Доступ к элементу структуры по указателю с помощью операции "→" в виде: <указатель на структуру>"→"<элемент_структуры>. Так, обращения pd→year и (*pd).year эквивалентны. Круглые скобки (*pd) необходимы, поскольку операция "." доступа к элементу структуры старше, чем "*".
  • Определение адреса структуры с помощью операции "&".
  • Присваивание структуры как единого целого.
    #include <iostream>
    using namespace std;
     
    struct date 
    { 
    	int day; 
    	int month; 
    	int year; 
    	char mon_name[12];
    };
     
    date a = { 14,7,1954,"July" };
    date b;
     
    void main ()
    {
    	// показ содержимого объекта a
    	cout<< a.day << " "; 
    	cout<< a.year << " "; 
    	cout<< a.month << " ";
    	cout<< a.mon_name << "\n\n";
     
    	// инициализация объкта b объектом a
    	b = a;
     
    	// показ содержимого объекта b
    	cout<< b.day << " "; 
    	cout<< b.year << " "; 
    	cout<< b.month << " ";
    	cout<< b.mon_name << "\n\n";
    }
  • Присваивание структуры как единого целого.
  • Передача структуры в качестве параметра функции и возвращение структуры в результате работы функции.
    #include <iostream cpp>
    using namespace std;
    
    struct date 
    { 
    	int day; 
    	int month; 
    	int year; 
    	char mon_name[12];
    };
    
    void Show(date a){
    	// показ содержимого объекта a
    	cout<< a.day << " "; 
    	cout<< a.year << " "; 
    	cout<< a.month << " ";
    	cout<< a.mon_name << "\n\n";
    }
    
    date Put(){
    	// формирование объкта
    	date temp;
    	cout<<"DAY ? ";
    	cin>>temp.day;
    	cout<<"MONTH ? ";
    	cin>>temp.month;
    	cout<<"YEAR ? ";
    	cin>>temp.year;
    	cout<<"MONTH NAME ? ";
    	cin>>temp.mon_name;
    	return temp;
    }
    
    date a = { 14,7,1954,"July" };
    date b;
    
    void main ()
    {
    	// передача объекта в функцию
    	Show(a);
    
    	// получение объекта в качестве возвращаемого значения
    	b=Put();
    
    	// показ содержимого объекта b
    	Show(b);
    	
    }
  • Передача отдельных компонент структуры в качестве аргументов функции.

А теперь, рассмотрим порядок выполнения некоторых наиболее распространенных операций над элементами структуры на примере следующего описания:

struct
{
	int x;
	int *y;

} *p; // p - указатель на структуру.
  • (++p)→x - операция увеличивает p до доступа к x;
  • (p++)→x - операция увеличивает p после доступа к x (круглые скобки не обязательны, так как по старшинству раньше будет применена операция "→");
  • *p→y - выбирается содержимое объекта, на который указывает y;
  • *p→y++ - увеличивается y после обработки того, на что он указывает (аналогично *s++);
  • *p++→y - увеличивает p после выборки того, на что указывает y;
  • (*(*p).y)++ - увеличивает то, на что указывает y.

Можно отметить одно очень важное использование структур: создание новых типов данных. Существуют типы данных, гораздо более эффективные при решении определенных задач, чем массивы и структуры. Это очереди, двоичные деревья, множества, таблицы и графы. Многие из этих типов создаются из "связанных" структур. Обычно каждая такая структура содержит один или два типа данных плюс один или два указателя на другие структуры такого же типа. Указатели служат для связи одной структуры с другой и для обеспечения пути, позволяющего вести поиск по всей структуре.

Объединения union

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

union
  {
   <имя типа1> <компонента1>;
   <имя типа2> <компонента2>;
        .     .      .
   <имя типаN> <компонентаN>;
  }

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

Доступ к компонентам объединения осуществляется тем же способом, что и к компонентам структур.

Пример.

#include <iostream>
using namespace std;
 
union Test
{
   int a;
   char b;
 
}kkk;
 
void main ()
{  
  kkk.a = 65;
  cout<<kkk.a<<" "; // число 65
  cout<<kkk.b;// символ А (соответствующий этому числу)
}

В качестве более осмысленного примера объекта типа union рассмотрим объединение geom_fig[1]:

union
  {
   int radius; // Окружность. 
   int a[2]; // Прямоугольник. 
   int b[3]; // Треугольник.
  } geom_fig;

В этом примере обрабатывается только активный компонент, то есть компонент, который последним получает свое значение. Например, после присваивания значения компоненту radius не имеет смысла обращение к массиву b.

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

Объединения применяются для:

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

Таким образом, после задания рассмотренной структуры данных в программе будет находиться переменная, которая на законных основаниях может хранить "в себе" значения нескольких типов.

Читайте также

Обзор игрового хостинга Realms Hosting: Minecraft, RUST, Counter-Strike. PQ VPS сервера в 28+ странах.