# 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]`), но можно обойтись и без этого **Очень часто есть хвостовое выравнивание для массивов из структур** Чтобы избежать хвостовое выравнивания при создании массива струкр - можно передалать логику работы алгоритма на **структуру массивов**! (вместо массива структур)