Структуры, typedef, объединения и перечисления

⏱ 25 мин · 🧩 заданий: 5

Структуры

Структура объединяет несколько полей разных типов в один объект:

struct point {
    int x;
    int y;
};

struct point p = {3, 4};       /* инициализация по порядку */
struct point q = {.y = 1};     /* именованная, x = 0 */
p.x = 10;                      /* доступ к полю */

struct point *pp = &p;
pp->y = 20;                    /* через указатель: то же, что (*pp).y */

typedef

typedef даёт типу короткое имя. Так в экзаменационной задаче объявлена структура разделяемой памяти:

typedef struct
{
    int state;              /* свободное поле — подсказка: пригодится для синхронизации */
    unsigned int counter;
    pid_t pid;
    pid_t ppid;
} Mem;

Mem *mem = mmap(NULL, sizeof(Mem), PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);
mem->counter = 0;

Без typedef пришлось бы везде писать struct имя.

Задача 8, пункт (b)

Условие разрешает добавлять поля в разделяемую память. Это значит, что в Mem можно дописать семафоры (sem_t), массивы, счётчики — всё, что нужно для синхронизации процессов.

Выравнивание

Процессору удобнее читать int по адресу, кратному 4, а double — кратному 8. Компилятор вставляет между полями пустые байты:

struct S { char c; double d; char e; }; sizeof = 24 offset: 0 1 ... 7 8 ............ 15 16 17 ... 23 ┌───┬───────┬──────────────────┬───┬──────────┐ │ c │ pad │ d │ e │ pad │ └───┴───────┴──────────────────┴───┴──────────┘ struct T { double d; char c; char e; }; sizeof = 16

Правила: каждое поле выравнивается по своему размеру, а размер всей структуры кратен самому строгому выравниванию среди полей. Смещение поля можно узнать макросом offsetof(struct S, d) из <stddef.h>.

Объединения

union value {
    int i;
    double d;
    char bytes[8];
};               /* sizeof = 8: все поля начинаются с одного адреса */

union value v;
v.d = 1.0;
printf("%02x\n", (unsigned char)v.bytes[7]);   /* посмотреть байты double */

В системном коде объединения используются, когда объект хранит одно из нескольких представлений. Например, в ядре Linux в структуре индексного дескриптора есть объединения для данных разных типов файлов, а union sigval передаёт с сигналом реального времени либо число, либо указатель.

Перечисления

enum state { FREE, FULL };          /* FREE = 0, FULL = 1 */
enum color { RED = 1, GREEN = 2, BLUE = 4 };

Константы перечисления — обычные целые числа, но с говорящими именами.

Битовые поля

struct pte {                 /* упрощённая запись таблицы страниц i386 */
    unsigned present  : 1;   /* P — страница в памяти */
    unsigned rw       : 1;   /* R/W — разрешена запись */
    unsigned user     : 1;   /* U/S — доступна из режима пользователя */
    unsigned pwt      : 1;
    unsigned pcd      : 1;
    unsigned accessed : 1;   /* A — бит доступа */
    unsigned dirty    : 1;   /* D — бит грязности */
    unsigned pat      : 1;
    unsigned global   : 1;
    unsigned avail    : 3;
    unsigned frame    : 20;  /* номер физического кадра */
};                           /* ровно 32 бита */

Так удобно описывать аппаратные структуры. Биты accessed и dirty мы подробно разберём в модуле о виртуальной памяти — это задача 5 экзамена.

Итог

  • Структура — набор полей; . для объекта, -> для указателя.
  • typedef struct {...} Mem; — короткое имя типа.
  • Компилятор выравнивает поля; sizeof структуры может быть больше суммы полей.
  • union — поля на одном месте; enum — именованные целые; битовые поля описывают аппаратные форматы.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Написать код

Объявите через typedef структуру Mem с полями: int state, unsigned int counter, pid_t pid, pid_t ppid — как в задаче 8 экзамена.

Задание 2 Ввод ответа

Чему равен sizeof(Mem) на Linux x86-64, если все четыре поля — по 4 байта (pid_t — это int)?

Задание 3 Ввод ответа

Чему равен sizeof(struct S) на x86-64?

struct S {
    char c;
    double d;
    char e;
};
Задание 4 Один вариант ответа

Чем объединение (union) отличается от структуры?

Задание 5 Написать код

Объявите перечисление enum state { FREE, FULL }; и функцию int is_full(const Mem *m), возвращающую m->state == FULL.

Войдите, чтобы отмечать пройденные уроки.