Добавил:
omninoy
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:ЛР-4 / lab4
.cpp#include <iostream>
using namespace std; // используем пространство имён std
// 2.1 типизированные и нетипизированные указатели
void task_2_1() { // объявляем функцию без параметров
int a = 42; // объявляем переменную a и инициализируем значением 42
int* typed_ptr = &a; // объявляем типизированный указатель, присваиваем адрес a
void* untyped_ptr = &a; // объявляем нетипизированный указатель, присваиваем адрес a
cout << "typed_ptr: " << *typed_ptr << "\n"; // выводим значение через разыменование
// typed_ptr = untyped_ptr; // ошибка в c++: нужно явное приведение типа
typed_ptr = static_cast<int*>(untyped_ptr); // безопасное приведение void* к int*
cout << "after cast: " << *typed_ptr << "\n\n"; // выводим значение после приведения
untyped_ptr = typed_ptr;
}
// 2.2 указатели на данные и на функции
int add(int x, int y) { return x + y; } // функция сложения двух чисел
void task_2_2() { // объявляем функцию
int val = 10; // объявляем переменную val со значением 10
double val1 = 20.1;
int* data_ptr = &val; // указатель на данные, хранит адрес val
double* data_ptr1 = &val1;
int (*func_ptr)(int, int) = &add; // указатель на функцию add
cout << "func ptr razim: " << *func_ptr << "\n\n";
cout << "dataptr: " << data_ptr << "\n\n";
cout << "dataptr: " << data_ptr + 1 << "\n\n";
cout << "dataptr: " << data_ptr1 << "\n\n";
cout << "dataptr: " << data_ptr1 + 1 << "\n\n";
cout << "data via ptr: " << *data_ptr << "\n"; // выводим значение через указатель на данные
cout << "func call: " << func_ptr(5, 3) << "\n"; // вызываем функцию через указатель
cout << "func addr: " << static_cast<void*>(func_ptr) << "\n\n"; // выводим адрес функции
}
// 2.3 разница между указателем и указуемым объектом
void task_2_3() { // объявляем функцию
int x = 10, y = 20; // объявляем две переменные с начальными значениями
int* p1 = &x; // указатель p1 хранит адрес переменной x
int* p2 = &y; // указатель p2 хранит адрес переменной y
cout << "addresses p1=" << p1 << ", p2=" << p2 << "\n"; // выводим адреса из указателей
cout << "values *p1=" << *p1 << ", *p2=" << *p2 << "\n"; // выводим значения через разыменование
cout << "address comparison (p1==p2): " << (p1 == p2) << "\n"; // сравниваем адреса
cout << "comparison of values(*p1==*p2): " << (*p1 == *p2) << "\n"; // сравниваем значения
*p1 = *p2; // копируем значение из *p2 в *p1 (косвенное присваивание)
p1 = p2; // копируем адрес из p2 в p1 (теперь p1 указывает на y)
cout << "after *p1=*p2 and p1=p2: x=" << x << ", *p1=" << *p1 << "\n\n"; // выводим результаты
}
// 2.4 указатель-константа vs указатель на константу
void task_2_4() { // объявляем функцию
int a = 1, b = 2; // объявляем две переменные
int* const ptr_const = &a; // константный указатель: адрес фиксирован, значение можно менять
const int* ptr_to_const = &a; // указатель на константу: значение фиксировано, адрес можно менять
*ptr_const = 10; // ok: меняем значение по адресу, на который указывает ptr_const
// ptr_const = &b; // ошибка: нельзя изменить адрес константного указателя
// *ptr_to_const = 20; // ошибка: нельзя менять значение через указатель на константу
ptr_to_const = &b; // ok: можно переназначить указатель на другой адрес
cout << "ptr_const -> " << *ptr_const << "\n"; // выводим значение через константный указатель
cout << "ptr_to_const -> " << *ptr_to_const << "\n\n"; // выводим значение через указатель на константу
}
// 2.5 многоуровневые указатели
void task_2_5() { // объявляем функцию
int val = 99; // объявляем переменную со значением 99
int* p1 = &val; // указатель первого уровня на val
int** p2 = &p1; // указатель второго уровня на p1
int*** p3 = &p2; // указатель третьего уровня на p2
cout << "val: " << val << "\n"; // выводим исходное значение
cout << "*p1: " << *p1 << "\n"; // разыменовываем один раз
cout << "**p2: " << **p2 << "\n"; // разыменовываем два раза
cout << "***p3: " << ***p3 << "\n\n"; // разыменовываем три раза
}
// 2.6 указатели vs ссылки
void task_2_6() { // объявляем функцию
int x = 5; // объявляем переменную
int* ptr = &x; // указатель на x
int& ref = x; // ссылка на x (псевдоним)
*ptr = 10; // меняем x через указатель
int* ref1 = &ref; // меняем x через ссылку
// ptr = nullptr; // указатель может быть нулевым (закомментировано)
// int& bad_ref; // ошибка: ссылку нужно инициализировать при объявлении
cout << "x after edits: " << x << "\n"; // выводим изменённое значение x
cout << "ptr address: " << ptr << ", ref refers to the same address\n"; // выводим адрес
cout << "sizeof(ptr)=" << sizeof(ptr) << " bytes, sizeof(ref)=" << sizeof(ref) << " bytes\n\n"; // размеры
cout << "ref: " << static_cast<int*>(ref1) << "\n\n";
}
int main() { // точка входа в программу
task_2_1(); task_2_2(); task_2_3(); task_2_4(); task_2_5(); task_2_6(); // вызываем все функции
return 0; // завершаем программу с кодом успеха
} 