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

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

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

Как мы уже ни раз были свидетелями: всё, что у нас есть в Си – данные. Однако, встроенных типов данных не так уж и много, а хочется удобств... И в каком-нибудь 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));
}