Объявления структур
«Объявление структуры» именует тип и задает последовательность переменных значений («элементы» или «поля» структуры), которые могут иметь разные типы. Необязательный идентификатор — тег — предоставляет имя типа структуры и может использоваться в последующих ссылках на тип структуры. Переменная этого типа структуры включает определенную этим типом последовательность целиком. Структуры в языке C аналогичны типам, известным в других языках как «записи».
Синтаксис
struct-or-union-specifier :
struct-or-union identifier opt struct-declaration-list >
struct-or-union identifier
struct-or-union :
struct
union
struct-declaration-list :
struct-declaration
struct-declaration-list struct-declaration
struct-declaration :
specifier-qualifier-list struct-declarator-list ;
specifier-qualifier-list :
type-specifier specifier-qualifier-list необ.
type-qualifier specifier-qualifier-list необ.
struct-declarator-list :
struct-declarator struct-declarator-list , struct-declarator
struct-declarator :
declarator
type-specifier declarator Выбрать : constant-expression
Объявление типа структуры не выделяет место для структуры. Это только шаблон для последующих объявлений переменных структуры.
Ранее определенный identifier (тег) можно использовать для ссылки на тип структуры, определенный в другом месте. В этом случае не может быть повторен до тех пор, struct-declaration-list пока определение является видимым. Объявления указателей на структуры и объекты typedef для типов структуры могут использовать тег структуры до определения типа структуры. Однако определение структуры необходимо получить до выполнения каких-либо фактических действий с размером полей. Это использование является неполным определением типа и тега типа. Для того чтобы это определение стало полным, определение типа должно отображаться позже в той же области.
Задает struct-declaration-list типы и имена элементов структуры. Аргумент struct-declaration-list содержит одно или несколько объявлений переменных или битовых полей.
Каждая переменная, объявленная в struct-declaration-list , определяется как член типа структуры. Объявления переменных внутри struct-declaration-list имеют ту же форму, что и другие объявления переменных, рассматриваемые в этом разделе, за исключением того, что объявления не могут содержать описатели класса хранения или инициализаторы. Элементы структуры могут содержать любые типы переменной, кроме типа void , неполного типа или типа функции.
Член не может быть объявлен как имеющий тип структуры, в которой он отображается. Однако элемент можно объявить как указатель на структурный тип, в котором он отображается, при условии, что этот структурный тип имеет тег. Он позволяет создавать связанные списки структур.
Структуры имеют ту же область видимости, что и другие идентификаторы. Идентификаторы структур должны отличаться от всех тегов структур, объединений и перечислений с той же областью видимости.
Каждый элемент struct-declaration в struct-declaration-list должен быть уникальным в пределах списка. Однако имена идентификаторов в struct-declaration-list не обязательно должны отличаться от обычных имен переменных или идентификаторов в других списках объявлений структуры.
Доступ к вложенным структурам можно осуществлять так же, как если бы они были объявлены на уровне области файлов. Например, с данным объявлением
struct a < int x; struct b < int y; >var2; > var1;
оба объявления являются допустимыми:
struct a var3; struct b var4;
Примеры
В следующих примерах показаны объявления структуры.
struct employee /* Defines a structure variable named temp */ < char name[20]; int id; long class; >temp;
Структура employee содержит три члена: name , id и class . Член name — это 20-элементный массив, а id и class — простые элементы с типом int и long соответственно. Идентификатор employee является идентификатором структуры.
struct employee student, faculty, staff;
В этом примере определяются три переменных структуры: student , faculty и staff . Каждая структура имеет такой же список из трех элементов. Эти элементы объявлены как имеющие структурный тип employee , определенный в предыдущем примере.
struct /* Defines an anonymous struct and a */ < /* structure variable named complex */ float x, y; >complex;
Структура complex содержит два элемента с типом float — x и y . Тип структуры не имеет тегов и, следовательно, является безымянным или анонимным.
struct sample /* Defines a structure named x */ < char c; float *pf; struct sample *next; >x;
Первые два элемента структуры — это переменная char и указатель на значение float . Третий элемент, next , объявляется как указатель на определяемый структурный тип ( sample ).
Анонимные структуры могут быть полезны, если имя тега не требуется, например, когда одно объявление определяет все экземпляры структуры. Пример:
struct < int x; int y; >mystruct;
Встроенные структуры часто являются анонимными.
struct somestruct < struct /* Anonymous structure */ < int x, y; >point; int type; > w;
Блок, относящийся только к системам Microsoft
Компилятор позволяет использовать безразмерный массив или массив нулевого размера в качестве последнего члена структуры. Это полезно, если размер массива констант отличается при использовании в различных ситуациях. Объявление такой структуры выглядит следующим образом.
struct identifier set-of-declarations type array-name []; >;
Безразмерные массивы могут отображаться только в качестве последнего члена структуры. Структуры, содержащие объявления безразмерных массивов, могут вкладываться в другие структуры при условии, что никакие другие элементы не объявлены ни в одной из внешних структур. Массивы таких структур не допускаются. Оператор sizeof , если он применен к переменной этого типа или к самому типу, предполагает, что размер массива равен 0.
Объявления структуры также можно указать без декларатора, когда они являются членами другой структуры или объединения. Уровень имен полей повышается до уровня внешней структуры. Например, безыменная структура выглядит следующим образом:
struct s < float y; struct < int a, b, c; >; char str[10]; > *p_s; . . . p_s->b = 100; /* A reference to a field in the s structure */
Дополнительные сведения о ссылках на структуры см. в разделе Структура и члены союза.
Завершение блока, относящегося только к системам Майкрософт
Структуры
Структура — это совокупность переменных, объединенных одним именем, предоставляющая общепринятый способ совместного хранения информации. Объявление структуры приводит к образованию шаблона, используемого для создания объектов структуры. Переменные, образующие структуру, называются членами структуры. (Члены структуры также часто называются элементами или полями.)
Обычно все члены структуры связаны друг с другом. Например, информация об имени и адресе, находящаяся в списке рассылки, обычно представляется в виде структуры. Следующий фрагмент кода объявляет шаблон структуры, определяющий имя и адрес. Ключевое слово struct сообщает компилятору об объявлении структуры.
struct addr char name[30];
char street [40]; char city[20];
char state[3];
unsigned long int zip;
>;
Объявление завершается точкой с запятой, поскольку объявление структуры — это оператор. Имя структуры addr идентифицирует структуру данных и является спецификатором типа. Имя структуры часто используют как ярлык.
На данный момент на самом деле не создано никакой переменной. Определена только форма данных. Для объявления настоящей переменной, соответствующей данной структуре, следует написать:
struct addr addr_info;
В данной строке происходит объявление переменной addr_info типа addr. При объявлении структуры определяется переменная смешанного типа. До тех пор, пока не будет объявлена переменная данного типа, она не будет существовать.
Когда объявлена структурная переменная, компилятор автоматически выделяет необходимый участок памяти для размещения всех ее членов. Рис. показывает размещение addr_info в памяти.
Определение структурных переменных.
Слово «структура» используется двояко. Во-первых, в смысле «структурного шаблона», о котором мы только что рассказали. Шаблон является схемой без содержания; он сообщает компилятору, как делать что-либо, но не вызывает никаких действий в программе. Следующий шаг заключается в создании «структурной переменной»; это и есть второй смысл слова структура.
Строка нашей программы, создающая структурную переменную, выглядит так:
struct book libry;
На основании этого оператора компилятор создает переменную libry. Согласно плану, установленному шаблоном book, он выделяет память для символьного массива, состоящего из MAXTIT-элементов, для символьного массива из MAXAUT-элементов и для переменной типа float. Эта память объединяется под именем libry. (В следующем разделе мы расскажем, как ее «разъединить», если понадобится.)
В этом описании struct book играет ту же роль, что и int или float в своих описаниях. Например, мы могли бы описать две переменные типа struct book или даже указатель на этот тип структуры:
struct book doyle panshin, *ptbook;
Каждая структурная переменная, doyle и panshin, имела бы части title, author и value. Указатель ptbook мог бы ссылаться на doyle, panshin или любую другую book-структуру. Для компьютера оператор нашей программы
struct book libry; является сокращенной записью
char title [MAXTIT];
char author [MAXAUT];
> libry; /* присоединяет имя переменной к шаблону */
Другими словами, процесс определения структурного шаблона и процесс определения структурной переменной можно объединить в один этап. Объединение шаблона и определений переменных является именно тем случаем, когда не нужно использовать имя типа структуры:
char title [MAXTIT];
char author [MAXAUT];
Форма с именем типа структуры удобнее, если вы используете структурный шаблон более одного раза.
Есть один аспект определения структурной переменной, который не нашел отражения в нашем примере — инициализация. Теперь мы хотим заняться этим вопросом.
Структуры С и C++.
Структурированные данные весьма распространены в повседневной жизни. Картотека, содержащая адреса знакомых, номера телефонов и прочую информацию, является структурой связанных атрибутов. Список любимых компакт-дисков или пластинок также является структурой; каталог диска — структура. В этих примерах используются структуры, но что же это такое? Структуру буквально можно рассматривать как набор переменных различных типов, образующих единый объект. Этот отдельный объект и является структурой.
Структуры С и C++: синтаксис и правила.
В языках С или C++ структура создается при помощи ключевого слова struct, за которым следуют необязательное поле тега (tag) и список элементов структуры. Поле тега используется для создания других переменных данного структурного типа. Синтаксис структуры с необязательным полем тега выглядит следующим образом:
тип_элемента элемент 1;
тип_элемента элемент 2;
тип_элемента элемент З;
Описание структуры заканчивается точкой с запятой, поскольку на самом деле оно является оператором С и C++. В некоторых примерах в данной главе используется структура, подобная следующей:
char sztype [iSTRING15 + iNULL_CHAR]; //тип
char szmodel[iSTRING15 + iNULL_CHAR]; //модель
char sztitle[iSTRING20 + iNULL_CHAR]; //бортовой номер
int iyear; // год выпуска
long int lmotor_hours; // ресурс двигателя
float fsaleprice; // продажная стоимость
Данная структура создана при помощи ключевого слова struct, за которым следует поле тега или тип структуры. В этом примере stboat является теговым полем структуры.
Объявление этой структуры содержит несколько элементов: sztype, szmodel и sztitle являются строками заданной длины, заканчивающимися null-символом. За ними следуют целое iyear, длинное целое lmotor_hours и число с плавающей точкой fsaleprice. Эта структура используется для хранения коммерческой информации о катере или лодке.
Таким образом описан новый гипотетический структурный тип stboat. Однако, с этой структурой не связана никакая переменная; для этого в программе можно использовать следующий оператор:
struct stboat stused_boat;
Этот оператор описывает переменную stused_boat, имеющую тип struct stboat. Обратите внимание на то, что в объявлении нужно использовать поле тега структуры. Если данный оператор располагается в некоторой функции, то структура stused_boat имеет локальную область действия внутри этой функции. Если оператор находится в программе вне всех функций, то структура имеет глобальную область действия. Также можно объявить структурную переменную, используя следующий синтаксис:
char sztype [iSTRING15 + iNULL_CHAR];
char szmodel[iSTRING15 + iNULL_CHAR];
char sztitle[iSTRING20 + iNULL_CHAR];
long int lmotor_hours;
Объявление переменной заключается между фигурной скобкой, закрывающей структуру (>), и обязательной точкой с запятой. В обоих примерах переменная stused_boat объявляется как структура типа stboat. На практике, если со структурным типом связывается только одна переменная, поле тега можно убрать, поэтому предыдущий пример можно записать и так:
char sztype [iSTRING15 + iNULL_CHAR];
char szmodel[iSTRING15 + iNULL_CHAR];
char sztitle[iSTRING20 + iNULL_CHAR];
long int lmotor_hours;
Заметьте, что в этом объявлении структуры отсутствует поле тега и создается так называемый анонимный структурный тип. Поскольку оператор описывает единственную переменную, stused_boat, то нигде в приложении нельзя создать другую переменную такого же типа. Если поле тега структуры отсутствует, то такой синтаксис не позволяет ссылаться на этот новый тип. Однако, с одним структурным типом можно связать несколько переменных, не указывая поле тега; это показано в следующем примере:
char sztype [iSTRING15 + iNULL_CHAR];
char szmodel[iSTRING15 + iNULL_CHAR];
char sztitle[iSTRING20 + iNULL_CHAR];
long int lmotor_hours;
> stboat1, stboat2, stboat3;
Так же, как и для любых других переменных, компиляторы С и C++ выделяют необходимую память для элементов структуры. Чтобы определить, нужно ли поле тега в объявлении структуры, нужно ответить на следующие вопросы: «Нужно ли где-нибудь в программе создавать другие переменные такого структурного типа?» и «Нужно ли передавать структурный тип в функции?» Если на какой-нибудь из вопросов имеется положительный ответ, то поле тега — необходимо.
Структуры C++: расширения синтаксиса и правил.
Во многих случаях С можно считать подклассом языка C++. В общем, это означает, что все программы на С будут работать в среде C++.
ПРИМЕЧАНИЕ. Если использовать методы проектирования С в программах на C++, то зачастую можно упустить более развитые и простые возможности C++.
Описанные выше примеры объявлений структуры работают с компиляторами С и C++. В C++, однако, имеется еще один способ объявления переменной некоторого структурного типа. В этой краткой записи, имеющейся только в C++, отсутствует необходимость повторять ключевое слово struct. Это тонкое различие отражено в следующем примере:
/* Объявление структуры, допустимое в С и C++ */
struct stboat stused_boat;
// Объявление структуры, возможное только в C++
stboat stused_boat;
C++. Структуры. Часть 1. Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR. Объявление и инициализация структурной переменной
Структуры. Часть 1. Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR . Объявление и инициализация структурной переменной
Поиск на других ресурсах:
1. Какое отличие между базовыми и составными типами данных?
Все типы данных в C++ делятся на:
- базовые типы данных ;
- составные (агрегатные) типы данных.
Переменные базовых типов данных состоят из одного элемента данных. Переменные составных типов данных содержат два и больше элемента данных.
2. Какие типы данных в C++ принадлежат к составным или агрегатным типам данных?
Составные типы данных еще называют агрегатными или конгломератными типами данных.
К составным или агрегатным типам данных принадлежат:
- массивы;
- структуры;
- объединения;
- перечисления ( enumeration );
- классы.
3. Что называется структурой в C++ ? Что называется полем структурной переменной?
Структура – это объединения одной или больше переменных в одной области памяти, которая имеет одно имя.
Структура – это объединение (группирование) переменных, которые родственны между собою по некоторому критерию.
Переменные, входящие в структуру называются полями структуры. Такие переменные могут быть разных типов. Имена полей (переменных) в одном шаблоне должны быть уникальными. Однако, в разных шаблонах имена могут повторяться.
4. Каким образом классифицируются структуры в среде CLR ? Native -структуры. Managed -структуры
Среда CLR поддерживает объявление структур двух видов:
- native -структуры;
- managed -структуры или управляемые структуры.
Native -структуры – это классические структуры языка C/C++.
Managed -структуры – это структуры, которые размещаются в памяти, которая выделяется и управляется средой CLR .
Managed -структуры могут быть объявлены с одним из двух квалификаторов:
- квалификатор ref – означает, что структура есть ссылочного типа;
- квалификатор value – означает, что структура есть типом-значением.
Отличие между квалификаторами ref и value состоит в способе выделения памяти для указателя на структуру. Более подробно работа с указателями на managed -структуры описана здесь .
5. Какая общая форма объявления native -структуры (шаблона структуры)?
Для объявления native -структуры (или шаблона структуры) используется ключевое слово struct . Общая форма объявления структуры:
struct имя_типа_структуры < тип элемент_1; тип элемент_2; . тип элемент_N; > структурные_переменные;
- имя_типа_структуры – название шаблона структуры. Шаблон структуры описывает новый тип данных, который может быть использован в дальнейшем в программе на C++ ;
- тип – тип данных, которые имеются в наличии на данный момент в программе;
- элемент1 , элемент2 , …, элементN – названия элементов (переменных), входящих в структуру. Элементы структуры еще называются полями структуры;
- структурные_переменные – это переменные, которые есть структурами. В случае объявления шаблона структуры структурные_переменные могут отсутствовать (смотрите следующие пункты).
6. Какая общая форма объявления managed -структуры с квалификаторами ref и value ?
Общая форма объявления структуры (шаблона структуры) с квалификатором ref :
ref struct имя_типа_структуры < тип элемент_1; тип элемент_2; . тип элемент_N; > структурные_переменные;
Общая форма объявления структуры (шаблона структуры) с квалификатором value :
value struct имя_типа_структуры < тип элемент_1; тип элемент_2; . тип элемент_N; > структурные_переменные;
В вышеприведенных описаниях:
- имя_типа_структуры – название шаблона структуры. Шаблон структуры образовывает новый тип данных, который может быть использован в дальнейшем в программе;
- тип – тип данных, имеющихся на данный момент в программе;
- элемент1 , элемент2 , …, элементN – названия элементов (переменных), входящих в структуру. Элементы структуры еще называются полями структуры;
- структурные_переменные – это переменные, которые есть структурами. В случае объявления шаблона структуры структурные_переменные могут отстствовать.
Более подробно работа с managed -структурами описана в теме:
7. Что такое шаблон (формат) структуры? Примеры задания шаблона
Чтобы описать структурную переменную, нужно сначала задать шаблон структуры. Шаблон структуры еще называется формат структуры. При задании шаблона структуры память не выделяется. Шаблон – это только описание (информация), переменные каких типов должны входить в структуру.
Пример 1. Описание шаблона структуры, которая описывает информацию об отработанных часах работником.
Шаблон содержит следующую информацию:
- код работника;
- фамилия и имя работника;
- количество отработанных часов;
- расценка за 1 час.
// информация о работнике // шаблон структуры struct Worker < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час >;
В данном примере шаблон называется Worker . В шаблоне описываются следующие поля (переменные):
- code – код работника;
- name – имя работника;
- hours – количество отработанных часов;
- cost – расценка за 1 час.
Пример 2. Объявление шаблона с именем Laboratory , содержащего информацию о лаборатории в учебном заведении:
- номер лаборатории;
- название лаборатории;
- площадь лаборатории;
- количество посадочных мест.
// информация о лаборатории // шаблон структуры struct Laboratory < int number; char name; float area; int places; >;
Для managed-структур перед словом struct указывается квалификатора ref или value .
8. Что такое структурная переменная? Способы объявления структурных переменных. Доступ к полям структурной переменной
Структурная переменная – это переменная типа, который задан в шаблоне структуры. Если объявляется такая переменная, то происходит выделение памяти для нее. Структурная переменная еще называется экземпляром структуры.
Структурную переменную можно объявить несколькими способами:
- на основе шаблона, который был объявлен раньше;
- во время объявления шаблона;
- с помощью квалификатора typedef .
Ниже приведены все 3 способы объявления структурной переменной, которая базируется на основе шаблона Worker , описывающего информацию о работнике. Рассмотрен пример для native -структуры.
// информация о работнике // шаблон native-структуры struct Worker < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час >;
Тогда структурную переменную можна описать следующими способами.
Способ 1. Описание переменной на основе ранее заданного шаблона Worker . В этом случае сначала задается шаблон структуры, затем описывается переменная (экземпляр структуры).
// Способ 1. Описание переменной по ранее созданному шаблону Worker w; // для переменной w выделяется память // заполнение полей переменной w.code = 334; strcpy(w.name, "Johnson B."); w.hours = 23; w.cost = 12.85f;
В вышеприведенном примере объявляется переменная с именем w на основе ранее описанного шаблона Worker . Затем для примера заполняются поля структурной переменной.
Способ 2. Объявление переменной во время задания шаблона. В этом способе объединяется объявление шаблона структуры и создание экземпляра структуры (переменной).
// Способ 2. Объявление переменной w1 во время объявления шаблона struct Worker < int code; char name[50]; int hours; float cost; > w1;
Доступ к полям переменной w1 из другого прогаммного кода
// заполнение значениями полей переменной w1 w1.code = 123; strcpy(w1.name, "Williams D."); w1.hours = 33; w1.cost = 10.58f;
Способ 3. Объявление переменной на основе типа, созданного с помощью квалификатора typedef .
Пусть в некоторой части программы объявлен новый тип WORKER , который основан на структуре Wrk , содержащей информацию о работнике:
// ключевое слово typedef // объявление нового типа WORKER typedef struct Wrk < int code; char name[50]; int hours; float cost; > WORKER;
Тогда, чтобы использовать переменную с именем w2 типа WORKER , нужно написать следующий код:
// объявление переменной на основе типа, // заданного с помощью ключевого слова typedef WORKER w2; w2.code = 100; strcpy(w2.name, "Typedef"); w2.hours = 33; w2.cost = 21.33f;
В этом способе задавать имя шаблона структуры Wrk необязательно. То есть, следующая запись также есть корректной
// после слова struct название шаблона отсутствует typedef struct < int code; char name[50]; int hours; float cost; > WORKER;
9. Где можно задавать шаблон структуры в среде CLR ?
В среде CLR рекомендуется объявлять шаблон структуры или новый тип на базе структуры (средство typedef ) в отдельном «*.h» файле, например «MyStruct.h» . Тогда удобно подключать эту структуру в другие модули программы, например:
#include "MyStruct.h"
10. Как осуществляется инициализация структурной переменной при ее объявлении? Пример инициализации native -структурной переменной
Пусть задан шаблон структуры Worker
// шаблон native-структуры struct Worker < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час >;
Тогда инициализация структурной переменной может быть такой.
Способ 1. Объявление и инициализация переменной после того, как раньше был задан шаблон структуры Worker
Worker w = < 150, "Andrews", 45, 18.45f >; int d; d = w.code; // d = 150 float f; f = w.cost; // f = 18.45
Способ 2. Объединение задания шаблона, описания структурной переменной и ее инициализации.
// шаблон структуры struct Worker < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час > w1 = < 200, "Armstrong W.", 64, 22.34f >; . int d; float f; d = w1.code; // d = 200 f = w1.cost; // f = 22.34
Способ 3. Если задан тип с помощью квалификатора typedef , тогда инициализация структурной переменной будет следующей
// объявление нового типа WORKER typedef struct < int code; // код работника char name[50]; // имя работника int hours; // количество отработанных часов float cost; // расценка за 1 час > WORKER; . WORKER W = < 333, "Baxter N.", 34, 15.30f >; int d; float f; d = W.code; // d = 333 f = W.cost; // f = 15.30f
Связанные темы
- Структуры. Часть 2. Выделение памяти для структуры. Вложенные структуры. Массивы native -структур
- Структуры. Часть 3. Работа с managed -структурами в среде CLR . Квалификаторы ref и value . Объявление структурных переменных. Массивы managed -структурных переменных. Инициализация managed -структур
- Структуры. Часть 4 . Структуры и функции. Передача структуры в функцию в среде CLR . Возврат структуры из функции
- Функции.Часть 2. Функции и массивы. Передача одномерного и многомерного массива в функцию. Передача структуры и класса в функцию
- Указатели. Часть 3. Неуправляемые указатели и массивы. Указатель на структуру. Указатель на класс
- Указатели. Часть 6. Составные native и managed типы данных. Управляемые указатели ( ^ ) в среде CLR . Выделение памяти. Квалификаторы ref и value . Управляемые указатели ( ^ ) на структуры и классы