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