Введение |
Операторы |
Операции |
Переменные и типы |
Пояснения к курсовой работе |
Препроцессор |
Работа с файлами |
Стандарты безопасного кодирования |
Указатели и динамическая память |
Функции и модули |
Ввод-вывод |
Несколько переменных, описывающих разные свойства одного объекта предметной области можно объединить в структуру. Каждый элемент структуры имеет уникальное имя. В отличие от массива элементы структуры могут иметь разные типы.
В языке C структуру сначала рекомендуется определить как тип и только после этого определять наборы такого типа:
typedef
или
tt"typedef" quad tt"struct" quad { "тип"_1 quad "элемент"_1; quad "тип"_2 quad "элемент"_2; quad ...} quad "имя";
В C++
tt"struct" quad "имя" { "тип"_1 quad "элемент"_1; quad "тип"_2 quad "элемент"_2; quad ...};
определяет тип с тем же именем. При использовании такого определения в C вместо простого имени придется указывать struct
"имя".
typedef
часто используется для сокращения названия типа из нескольких слов:
typedef unsigned long long ull;
typedef unsigned char byte;
ull a; // unsigned long long a;
byte b; // unsigned char b;
Для доступа к элементам структуры (полям) используется операция .
: "имя_структуры" tt"." "имя_поля"
Список начальных значений для набора-структуры указывается в {}
через запятую. Можно явно указать, какому полю присваивается значение: tt"." "имя_поля" ="выражение". Если значение какого-либо поля явно не указано, то оно получает значение 0.
Примеры структур:
typedef struct { double x, y, z; } coord; // координаты в пространстве
typedef struct { // дата
char day; // день 1-31
char month; // месяц 1-12
int year; // год
} date;
typedef struct { // информация о человеке
char name[51]; // имя
date birthday; // дата рождения
char addr[101]; // адрес
char job[16]; // должность
int salary; // зарплата
} person;
Примеры определения и инициализации наборов-структур:
coord p1={1, 7, 2.5};
date d1;
person joe={"Joseph",{20,11,1942},"Washigton, DC","President",100000};
person team[5]= // массив лиц
{ {"Kamala", .job="Vice-president",.salary=150000},
{"Antony", .job="Secretary"}
};
Обращение к полям структуры:
printf("%lf lf lf\n",p1.x, p1.y,p1.z);
d1.day=12;
joe.birthday.day=d1.day;
В отличие от массивов структуры можно копировать целиком обычным присваиванием, в том числе в случаях, когда одним из полей является массив. Для копирования отдельного поля-массива нужно использовать memcpy
или strcpy
. Вместо присваивания полям значений по отдельности можно присвоить структуру-значение: ("спецификаторы" quad "тип") {"список_значений_для_полей"}
d1=joe.birthday; // копируем все поля
team[4]=joe; // копируем все поля
team[3]=team[2]; // копируем все поля
strcpy(team[3].addr,joe.addr); // но копируем одно поле-строку
joe.birthday=(date){30,4,1945}; // присваивание структуры-значения вместо joe.birthday.day=30; joe.birthday.month=4; ...
team[4]=(person){"Karine", {12,8,1974}, .job="Press Secretary"};
Когда структура является частью другой структуры и не используется отдельно, можно не вводить тип:
typedef struct {
char name[51]; // имя
struct { char day, month; int year; } birthday; // дата рождения
int salary; // зарплата
} person;
...
person p;
p.birthday.day=11;
Структуры можно использовать для упаковки нескольких небольших чисел в машинное слово:
#include <stdio.h>
#include <stdbool.h>
typedef struct {
int a:4; // число от -8 до 7
bool flag:1; // 0 или 1
unsigned b:10; // число от 0 до 1023
// +1 бит так как тип short требует выравнивание на 2 байта
short c; // попробуйте изменить на int
} packed;
typedef struct { // то же без упаковки
int a; // 4 байта
bool flag; // 1 байт +3 байта для выравнивание на 4 байта
unsigned b; // 4 байта
short c; // 2 байта +2 байта для выравнивание на 4 байта
} unpacked;
int main() {
packed x;
unpacked y;
printf("%d %d\n",sizeof(x),sizeof(y)); // 4 16
}