Программы
Структуры и объединения

Структуры и объединения

Базовые структуры в Си. Общие принципы работы с ними

Как мы уже ни раз были свидетелями: всё, что у нас есть в Си – данные. Однако, встроенных типов данных не так уж и много, а хочется удобств... И в каком-нибудь Java, Python, C# мы бы написали класс. В Си же у нас будут структуры!

Структуры

struct - структура двумерной точки

Структуры Си – композитный тип данных – возможность составлять из уже имеющихся типов более сложные. Никакой инкапсуляции и сокрытия деталей реализации – не забываем – просто представление байтов.

В распоряжении также указатели на структуры – можно делать рекурсивные типы данных, например, структуру типа дерева.

Для примера рассмотрим двумерную точку:

#include <stdio.h>

struct Point2d {
  int x;
  int y;
};

void print_point(struct Point2d point) {
  printf("<Point %d, %d>\n", point.x, point.y);
}

int main() {
  struct Point2d point = { -1, 1 };
  print_point(point);
}

typedef

Аналогично, но используем typedef для удобства – создадим алиас для типа, чтобы не писать постоянно struct.

#include <stdio.h>

typedef struct Point2d {
  int x;
  int y;
} Point2d;

void print_point(Point2d point) {
  printf("<Point %d, %d>\n", point.x, point.y);
}

int main() {
  Point2d point = { .y = -1, .x = 1};  // Ещё один способ инициализации
  print_point(point);

  Point2d point2 = point;  // Копирование
  point2.y = 255;
  print_point(point);

  Point2d *point3 = &point;  //*
  point3->x = 343;  // Разыменование - очередной синтаксический сахар
  print_point(point);
}

Также можно делать алиасы для более простых типов данных, например, использованный ранее тип size_t:

typedef unsigned long size_t;

То есть в общем случае мы можем дать другое название какому-либо типу:

typedef <какой-то тип> <его ещё одно название>;

Упражнение: считаем расстояние между точками

#include <stdio.h>
#include <math.h>

typedef struct Point2d Point2d;
struct Point2d {
  int x;
  int y;
};

int distance(Point2d *point_1, Point2d *point_2) {
  double x = (double)point_1->x - (double)point_2->x;
  double y = (double)point_1->y - (double)point_2->y;
  return sqrt(x * x + y * y);
}

int main() {
  Point2d a = { .y = -1, .x = 1};
  Point2d b = { .y = 1, .x = 1};
  printf("%d\n", distance(&a, &b));
}
Также может быть вам интересно:

Колбеки и функции высших порядков

Немного функционального программирования в Си

Читать »

Выравнивание структур

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

Читать »
Фото Как сделать свою middleware в Django (с примерами)

Как сделать свою middleware в Django (с примерами)

Middleware или "промежуточное программное обеспечение" - элегантный способ установить общие правила обработки запросов и ответов приложения. Давайте напишем парочку middleware, чтобы понять, как они работают.

Фото Как настроить отправку почты из Django

Как настроить отправку почты из Django

Письма об ошибках, отчёты на почту, восстановление паролей - всё это полезно при работе с сайтом. Django предоставляет удобный способ это сделать с минимумом настроек!

Фото Добавляем поддержку медиа-файлов в Django проект

Добавляем поддержку медиа-файлов в Django проект

Современные сайты редко ограничиваются только текстом и вёрсткой. Часто в заметках красуются фотографии, а рядом с описанием товаров - их изображения.

Фото Настройка журналирования (логирования) в Python с примерами

Настройка журналирования (логирования) в Python с примерами

Во время работы программы часто нужно сохранять некоторые важные записи о процессе выполнения команды. В Python есть довольно мощный модуль для работы с логами - давайте разберёмся с тем, как его использовать.

Фото Нет слов, одни... однострочники

Нет слов, одни... однострочники

На днях вышел пост со списком полезных однострочников для JavaScript программистов. Памятуя Perl-овую молодость, заглянул туда.

Фото Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

В Django вы можете передавать данные в шаблоны посредством контекстов. Контекст передаётся из контроллера (view в терминах Django), однако, если одни и те же данные нужны в разных местах, лучше сделать свой контекст-процессор.

Фото Пример своей консольной команды в Django проекте

Пример своей консольной команды в Django проекте

Если вы работали с Django проектом, то, скорее всего, запускали команды из консоли (manage.py). В Django есть простой способ писать свои команды для управления проектом.

Фото Разграничение прав доступа на Django сайте

Разграничение прав доступа на Django сайте

Почти на любом веб-сайте необходимо разделять пользователей на группы и предоставлять им разные возможности. В Django есть довольно серьёзная система прав доступа для пользователей - давайте её рассмотрим!