# 03 лекция Полная версия
## За жизнь
Rust - язык без стандарта, свой компилятор языка без стандарта создать невозможно, тк то, как работает компилятор разработчика языка и является фактически стандартом.
[IEEE 754-2008](https://ru.wikipedia.org/wiki/IEEE_754-2008) - как представляются числа в современном компьютере (C/C++)
Вольный пересказ - https://www.softelectro.ru/ieee754.html
## Переменные и Операторы
`int a, b = 5; // переменная a не инициализируется`
> Инициализуется только те переменные у которых стоит `=`
Локальные переменные без инициализации содержат мусор (рандомное значение), тк под локальные переменные место на стеке выделяется, но ничем не заполняется, может случиться 0, может не 0, из разных запусков - может случиться разное, из разных компиляций (release/debug) может случиться разное.
Вообще, ошибки обращения к неиницилизированным переменным - это очень частые ошибки.
Как искать обращение к неинициализированным переменным
1) Статические ситемы (анализаторы кода в онлайне, привязан к среде разроботки, замедляет её)
2) Динамические ситемы (может быть не привязан к среде, проверка при запуске под ним, бешенное замедление работы программы при запуске под ним, для больших программ можно не дождаться)
например [Intel Inspector](https://www.intel.com/content/www/us/en/developer/tools/oneapi/inspector.html)
---
```c
int main(void)
{
int a, b = 0, c; // b - инициализируется
// Выделилось место на стеке для a, b и c
return 0;
}
```
> `//` и `///` - это комментарий, начиная от этого места до конца строки (до перевода строки), компилятор игнорирует, можно писать что угодно
> если пишите комментарии на русском, надо посмотреть, чтобы кодировка файла в средее (текстовом редакторе) была `UTF-8`
```c
a = b + 3; //a == b + 3
a += b; // полный синоним a = a + b; //результат a == b + 3 + b
// (как и многие другие бинарные операции просто короткая запись)
// выдает результат в си значение a, после операции
```
---
-многие вещи в C/C++ имеют результат, некое значение, например операция `=` (присваивания) тоже имеет результат, почему можно писать `a = b = c`? (что это значит?)
```c
a = b = c; // эквивалент a = (b = c) или b = c; a = c;
```
> то есть операция `=` вместо того, чтобы просто присваивать ещё и отдает значение которое она присвоила.
`a = b;`, `a`, слево от `=` - то куда присваиваем, `b`, справо от `=` - значение, которое мы присваиваем, операция присваивания всегда левостороняя.
`a = b = c`, тоже самое `a = (b = c);` - всегда читается справа налево!
```
(a = b) = c; // в си НЕ СКОМПИЛИРУЕТСЯ
// НЕльзя в значение записать значение, например 5 = 3;
```
> В значение нельзя записать значение, можно только в обьект (переменную)
> Разница между объектом и значением видна только еcли мы туда пишем, если нет - нет
В си++ - в результате операции присваивания `=` отдается обьект, то есть `(a = b) = c;` будет эквивалентом `a = b; a = c;`, но `a = b = c` всё равно юудет читаться как в си, справа налево!
> Кажется, что это довольно глупая операция, ведь значение `b` сразу затрётся, но это если `a` и `b` простые типы, а в C++ всё может быть гораздо хитрее. Можно переобозначить операцию `=`, и он может выполнять совсем нетривиальные вещи.
---
Надо поподробнее остановиться на `a++` (постфиксный инкремент) и `++a` (префиксный инкремент)
```c
a++; // - постфиксная запись a = a + 1;
++a; // - префиксная запись a = a + 1;
```
> С точки зрения `a` разницы никакой (в си), а вот отдают они разное значение.
`a++;` результат - значение `a` до увеличения\
`++a;` результат - значение `a` после увеличения
```c
a = 2;
b = a++; // a=3, b=2 // сначала отдает значение, затем увеличивает
```
```c
a = 2;
b = ++a; // a=3, b=3 // сначала увеличивает, затем отдает значение
```
> Класс - обьединение переменных и функций, как структуры в си, только ещё со своими функциями, методами.
> В C++ если обьекты обычные (простые типы) - разници нет никакой, если это какие-то классы, то для них могут быть переопредленны операторы `a++` или `++a`, и они могут означать разное. В плюсах `a` может оказаться классом, а если так - `a++` будет создавать временный обьект, копию класса, что может сильно замедлять программу, например цикл. В двух словах: для сложных объектов в C++ вполне возможно, что будет оверхед (`i++` может создать временный объект), для простых int'ов – нет, для отдельно стоящего `i++` точно такой же код, как и `++i`.
**+, =, ++ и прочие операторы в C++ можно перопределить!**
(нельзя переопределить `.` и `:`)
### На что обратить внимание?
Один и тот же символ может означать разные операции, в зависимости от контекста, например `-`, может быть вычитанием, когда он используется в бинарном контексте, и может быть инвертированием знака, когда используется в унарном контексте.
```c
c = a - b; //вычитание, бинарный контекст
a = -a; //инвертирование знака, унарный контекст
```
У `*` вообще три разных контекста, бинарный, унарный и при создании переменной.
```c
c = a * b; //умножение, бинарный контекст
с = *ptr; //разыменовка, унарный контекст
int *d; //создание указателя, контекст при создании переменной
```
Хитрых операций много, а вот символов нет, в те времена (написания си) даже большие/маленькие буквы не везде различали
**У операций есть приоритет!** При одинаковом приоритете операции выполняются в нужном порядке, например для `+-` это слева направо, для `=` справа налево. То есть порядок зависит ещё и от контекста. (правила - [Operator Precedence](https://en.cppreference.com/w/cpp/language/operator_precedence)
>`a+++++a` что это означает в си?
>
>`(a++)+(++a)`, НЕ `((a++)++) + a` потому что в си операция `++` отдает значение, а не обьект!
В C++ `i++` и `++i` могут вернут объект
Не надо писать так`c = (a++)+(++a);` Нельзя в одной строке менять 2 раза переменную, выдаст неопределенное значение (зависит от порядка в моменте), тк порядок выполнения в си неопределён!
**Никогда не меняйте в выражение дважды одну переменную!**
Для большинства бинарных операций порядок выполнения не определен
Это справедливо и вызова функции нескольких аргументов: для аргументов функции, никто не обещает в каком порядке посчитаются аргументы функции, гарантируют, что они посчитаются перед непосредственном вызовом функции
`c = f() + g();` никто не обещает какая функция будет выполнена первой!
```c
int sum(int a, int b)
{
return a + b;
}
int print(int a)
{
printf("%d\n", a);
return a;
}
int main(void)
{
int result = sum(print(4), print(3)); //result == 7
// неопределенно в какой порядке напечатается на экран
// неопределенно вызовется сначала print(4) или print(3)
// гарантируется выполнение print(4) и print(3) до непосредственного вызова sum()
int result_2 = print(4) + print(3);
// в такой записи порядок тоже неопределён
// гарантируется выполнение print(4) и print(3) до сложения
}
```