Skip to content

Commit 7c4c864

Browse files
committed
Ad pointers module
1 parent 0e7c73c commit 7c4c864

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

src/08_pointers.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include <iostream> // cout, printf
2+
3+
int main() {
4+
5+
// 1. Память и адреса.
6+
7+
// При инициализации переменной под нее автоматически выделяется
8+
// свободный участок памяти, размер которого зависит от типа переменной.
9+
// Например, под тип int выделится 4 или 8 байтов (зависит от компилятора).
10+
int a = 7;
11+
int b = 11;
12+
13+
std::cout << "a = " << a << '\n';
14+
std::cout << "b = " << b << '\n';
15+
16+
// 2. Понятие указателя.
17+
18+
// В C++ мы можем получить адрес на участок памяти, в которой хранится переменная.
19+
// Для этого используется оператор взятие адреса & (амперсанд).
20+
int *pointer_to_a = &a; // адрес в памяти, т.е. указатель на переменную типа int
21+
22+
// Заметка 1: адрес переменной 'a' хранится в новой переменной под названием 'pointer_to_a'.
23+
24+
/*
25+
* Пояснения:
26+
* 1. int * - читаем справа налево: указатель * на переменную типа int => * на int
27+
* 2. указатель - это переменная, которая хранит в себе адрес на определенный участок памяти
28+
* 3. адрес - это некое число (обычно представляемое в 16-ой СС)
29+
* 4. Тип указателя должен соответствовать типу переменной, на которую он указывает!
30+
*/
31+
32+
/*
33+
* Повторение - мать ... твою!
34+
* Под переменную выделяется участок памяти, у которой есть адрес (адрес = число).
35+
* Адрес переменной можно получить, используя оператор взятия адреса & (амперсанд).
36+
* Указатель - это новая переменная со значением адреса другой переменной.
37+
*/
38+
39+
// Выведем адрес переменных 'a' и 'b' в стандартный поток вывода stdout.
40+
printf("&a = %X\n", pointer_to_a); // %X - вывода значения в 16-ой СС
41+
printf("&b = %X\n", &b);
42+
43+
// 3. Чтение данных по указателю.
44+
45+
// Замечательно, у нас есть адрес на участок памяти переменной 'a'.
46+
// Создадим новую переменную 'c' и скопируем туда значение переменной 'a'.
47+
// Для получения доступа к данным по указателю используется оператор разыменования * (звездочка).
48+
49+
int c = *pointer_to_a; // копируем в 'c' значение переменной, на которую ссылается указатель, т.е. 'a'
50+
51+
/*
52+
* Пояснения (rolling in the deep ... shit):
53+
* 1. pointer_to_a - переменная, которая хранит в себе адрес 'a'
54+
* 2. адрес нам не нужен, мы хотим получить значение, которое хранится в 'a'
55+
* 3. используем оператор * для "перехода" по адресу 'a' (тук-тук, 'a', выходи)
56+
* 4. 'a' "вышел" и дал нам увидеть свое лицо (хранимое значение)
57+
* 5. сохраняем (копируем) значение 'a' в переменную 'c' оператором =
58+
*/
59+
60+
std::printf("c = %d\n", c); // значение переменной равно значению 'a'
61+
std::printf("&c = %X\n", &c); // адрес не совпадает с адресом 'a'
62+
63+
// 4. Запись данных по указателю.
64+
65+
// Изменим значение переменной 'a' по указателю.
66+
*pointer_to_a = 3;
67+
68+
/*
69+
* Пояснения:
70+
* 1. pointer_to_a - переменная, которая хранит адрес 'a'
71+
* 2. при помощи оператора * "переходим" по адресу на участок памяти 'a'
72+
* 3. записываем в этот участок памяти новое значение оператором =
73+
*/
74+
75+
std::printf("a = %d\n", a); // значение переменной изменилось
76+
std::printf("&a = %X\n", &a); // адрес не изменился
77+
78+
// 5. Указатель, который никуда не ссылается.
79+
80+
// В С++ есть ключевое слово nullptr, которое обозначает, что указатель никуда не ссылается.
81+
int *null_pointer = nullptr; // Python: None, Java: null
82+
83+
// nullptr всегда ссылается на "несуществующий" участок в памяти, т.е. ноль
84+
std::printf("nullptr = %X\n", null_pointer);
85+
86+
// 6. Проверка и сравнение указателей.
87+
88+
// Проверка указателя на то, что он ссылается на "существующий" участок в памяти.
89+
90+
if (!null_pointer) {
91+
std::cout << "Pointer is nullptr\n";
92+
}
93+
94+
if (pointer_to_a) {
95+
std::cout << "Pointer 'a' is not nullptr\n";
96+
}
97+
98+
// На один и тот же участок памяти можно создать несколько указателей.
99+
int* pointer_to_a_1 = &a;
100+
int* pointer_to_a_2 = &a;
101+
102+
// Проверим, ссылаются ли они на один и тот же участок в памяти.
103+
if (pointer_to_a_1 == pointer_to_a_2) {
104+
std::cout << "pointers are equal\n";
105+
}
106+
107+
return 0;
108+
}

0 commit comments

Comments
 (0)