---
# System prepended metadata

title: 03 лекция Полная версия

---

# 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) до сложения
}
```