Summary Files Commits Branches @commit @diff @stats
path: root / src / teaching / upp-2023 / week5 / revision.du
blob: 37c7c8d21a3c4418b8cc49f50ceb84fcc9fe10a6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# Преговор - УПП, Седмица 5, 03.11.2023

## Указатели

Всяка променлива се съдържа някъде в паметта.
За да можем да определим къде дадено нещо е запазено, всяка клетка в паметта си има "адрес".
Адресът е едно цяло положително число.

Можем да вземем адреса на дадена променлива с оператора [`&`]:

```cpp
double a = 3.14159;
std::cout << (&a) << std::endl;

Tази програма ще върне адресът на променлива [`a`].

След като имаме адрес, бихме искали да работим със стойността на този адрес.
Това го правим с дерефериращия оператор [`*`]:

```cpp
double a = 3.14159;
std::cout << (*(&a)) << std::endl;

Тази програма връща стойността на адреса на променлива [`a`].

Променливи, които съдържат адреси се наричат указатели.
Синтаксисът на един указател е:

```cpp
<ТИП НА СТОЙНОСТТА> * <ИМЕ> = <АДРЕС>;

Тоест примерно:

```cpp
double a = 3.14159;
double * pointer = &a;

Звездата може да бъде долепена до типа или името на указателя:

```cpp
double* pointer1 = &a;
double *pointer2 = &a;

## Масиви

Ако искаме да запазим няколко последователни стойности, можем да използваме масиви.
Идеята е, че запазваме няколко адреса в паметта един след друг и запазваме само първия адрес.
Така първия елемент се намира на първия адрес, втория елемент се намира на първия адрес + 1 и так. нат.

Дефинираме масиви с контантна дължина така:

```cpp
<ТИП> <ИМЕ>[]  = { <СТОЙНОСТ 1>, <СТОЙНОСТ 2>, ..., <СТОЙНОСТ N> }; // масив с N елемента
<ТИП> <ИМЕ>[N]; // само ги дефинираме, обаче не ги инициализираме
<ТИП> <ИМЕ>[N] = { <СТОЙНОСТ> }; // дефинира всички N елементи със <СТОЙНОСТ>
<ТИП> <ИМЕ>[N] = { <СТОЙНОСТ 1>, <СТОЙНОСТ 2>, ..., <СТОЙНОСТ M> }; // където M <= N

Самото [`<ИМЕ>`] е указател, така че може да достъпваме стойности чрез указателна аритметика:

```cpp
int arr[2] = { 83, 18 };
std::cout << (*(arr + 1)) << std::endl;

Връща втория елемент, [`18`].

Или чрез по-приятния синтаксис с квадратни скоби:

```cpp
int arr[2] = { 83, 18 };
std::cout << (arr[1]) << std::endl;

Двете неща са еквивалентни, тоест [`name[x]`] е еквивалентно на [`*(name + x)`].

Когато един масив съдържа букви, наричаме го "низ" (string).
За да не трябва да следим дължината на един низ в друга променлива и да трябва да я подаваме, винаги завършваме нашия низ на "терминаращата нула" - [`'\0'`].