# 09 Лекция Полная версия
[TOC]
## Типы с плавующей точкой
> Много вычислений в числах с плавающей точкой - накапливают большую погрешность, немного разные реализации могут давать существо разную точность
Сравнивать можно только через `eps`
```c
if (a==b) // неправильно
if (fabs(a-b) < eps) // правильно
```
## Структуры
Массивы - способ обьединения однородных данных (одного типа)\
Структуры - способ обьединения разнородных данных (разных типов)
### Создание
Обычное использование:
```c
struct A
{
int x; // один int
float y; // один float
char z[4]; // массив 4х char
};
struct A a; //"struct A" - название нового типа
//"a" - название переменной типа "struct A"
```
Обратим внимание на `;` после структуры, она тут нужна потому что после структуры можно сразу содать обьекты типа нашей структуры.
```c
struct // Структуру можно даже не называть
// (не рекомендуется)
{
int x; // один int
float y; // один float
char z[4]; // массив 4х char
} a; //можем сразу создать обьект такого типа
```
> Структуру можно даже не называть, не рекомендуется тк есть спец эффекты, например при отладке имя структуры не покажется
Часто можно встретить: (Чтобы не писать `struct`)
```c
typedef struct A // 'A' можно не писать
{
int x;
float y;
char z[4];
} B;
B b;
```
ИЛИ
```c
struct A // 'A' нужно писать
{
int x;
float y;
char z[4];
};
typedef struct A B;
B b;
```
> У структур нет модификаторов доступа, в си такого нет, появляется только в си++
### Обращение к полям структур
```c
A a, b = {1, 2}; //в порядке сверху вниз (в самой структуре)
a.x; //доступ к переменной x
a.z[1]; //доступ к 1 элементу массива z
a = b; // можно скопировать поэлементно
```
Структуры можно скопировать поэлементно, что существенно отличает структуры от массивов. Если мы напишем так про массивы (`a = b`, где `a` и `b` массивы) - то ничего хорошего не произойдет, массивы будут интерпретированны как указатели и при компиляции нам скажут "что за ужас здесь творится". Чтобы скопировать массивы надо либо писать цикл либо вызвать специальную функцию копирования памяти (из одного места в другое). (либо же обернуть их в структуры)
**Массивы внутри структур ведут себя как структуры** (копируются полностью)
Структуры сразу ничем нельзя инициализировать, тк структура это не создание обьекта, **описание структуры - описание формата данных в памяти**. Описание расположения ничего не говорит о содержимом.
Можно иниц обьект при создании:
```c
typedef struct
{
int x;
int y;
} A;
A a = {.y=2, .x=1}; //a.x == 1 a.y == 2
//чтобы иниц. не по очереди
A b = {1, 2}; //b.x == 1 b.y == 2
A c = {1}; //c.x == 1 c.y == 0
A d = {}; //d.x == 0 d.y == 0
//не все компиляторы понимают
A e; // Мусор и в 'e.x' и в 'e.y'
```
`A a = {.y=2, .x=1};` Начиная с C99, нет в C++
`A d = {};` - компилятор инициализирует всё нулям, некоторые компиляторы не любят пустые `{}`
### Как хранится в памяти
Элементы структуры в памяти хранятся **ровно** в том порядке в котором их описали в структуре. Переставлять их компилятор не имеет права. Но это не означает что они лежат в памяти плотно.
```c
struct A
{
// первая переменная можно считать начитаеся с адреса 0
int x; // 4 байта
// дырка 4 байта
double y; // 8 байт
char z[4]; // 4 байта
// дырка 4 байт -
// - для выравнивания при создании массива структур
// всего 24 байта
};
```
Это так называемое **Выравнивание на родную границу**. Железкам **очень** нравится когда данные храняться по адресу кратному размеру данных
Для x86 архитектуры железок (x64 частный случай x86) практически не важно есть выразвнивание или нет (иногда небольшое замедление). В других железках программа может даже упасть, тк железо может не уметь читать невыравненные данные, либо может быть дикое замедление.
В си **по умолчанию все данные выравниваются на родную границу**, для этого копилятору может прийтись напихать дырок.
Первый `int` начаниется в начале структуры и начало структуры достаточно хорошо выразвненно для ВСЕХ элементов (можно считать что начинается с 0 адреса)
Чтобы **избежать** дырок в структуре - рекомендуется описывать структуры в порядке уменьшения рамера базового типа (`double -> int -> char[4]`), но можно обойтись и без этого
**Очень часто есть хвостовое выравнивание для массивов из структур**
Чтобы избежать хвостовое выравнивания при создании массива струкр - можно передалать логику работы алгоритма на **структуру массивов**! (вместо массива структур)