- •Базовые понятия информатики. Понятие «Информатика» и «Информация»
- •Информация
- •Информационные технологии
- •Понятие алгоритма. Свойства и классы алгоритмов. Формы представления алгоритмов
- •Понятие алгоритма. Базовые алгоритмические структуры
- •Представление данных в памяти персонального компьютера.
- •Принципы обработки программных кодов
- •Компиляторы
- •Интерпретатор
- •Язык с. История развития. Основные свойства языка
- •Отличительные особенности языкаC
- •Элементы языка c
- •Константы
- •Базовые типы данных
- •Директива #include
- •Использование void
- •Инструкция return
- •Описание переменных
- •Обработка данных. Операторы
- •Арифметические операторы
- •Приоритет операторов и порядок вычислений
- •Используемые алгоритмы обработки данных
- •Аккумуляторы
- •Преобразования типов данных
- •Декларации и дефиниции функций
- •Формальные и фактические параметры. Вызов функций
- •Возврат функцией значений
- •Переменные в функциях
- •Автоматические (локальные) переменные
- •Внешние (глобальные) переменные
- •Статические переменные
- •Передача параметров по значению
- •Передача параметров по ссылке
- •Значения параметров по умолчанию
- •Перегрузка функций
- •Рекурсия
- •Встроенные функции
- •Обработка символьных данных
- •Функция puts()
- •Функция putchar()
- •Функция printf()
- •Выбор правильных средств вывода информации
- •Функция gets()
- •Функция getchar()
- •Функция scanf()
- •Выбор соответствующих средств ввода данных
- •Управляющие структуры Структуры выбора (if / else)
- •Структуры выбора (switch/case/default)
- •Структуры повторения (циклы)
- •Использование цикла for
- •Использование цикла do...While (постусловие)
- •Использование цикла while (предусловие)
- •Операторы передачи управления Оператор безусловного перехода goto
- •Оператор break
- •Оператор continue
- •Препроцессор языка Си
- •Массивы Объявление переменной массива
- •Использование индексной переменной
- •Инициализация массива при объявлении
- •Передача массивов в функции
- •Использование констант при объявлении массивов
- •Символьные строки
- •Массивы строк
- •Алгоритмы сортировки массива
- •Поиск заданного элемента в массиве
- •Указатели
- •Объявление указателя
- •Указатели на массивы
- •Операции над указателями
- •Указатели на строку
- •Указатели на функцию
- •Функции, возвращающие указатель
- •Указатели на многомерные массивы
- •Массивы указателей
- •Динамическое распределение памяти
- •Структуры данных
- •Реализация одних структур на базе других
- •Очередь
- •Операции над очередями
- •Операции над стеками
- •Ссылочные реализации структур данных
- •Операции над списками
Объявление указателя
Так как указатель содержит адрес объекта, это дает возможность "косвенного" доступа к этому объекту через указатель. Предположим, что х - переменная, например, типа int, а рх - указатель, созданный неким еще не указанным способом. Унарная операция & выдает адрес объекта, так что оператор
рх = &х;
присваивает адрес х переменной рх; говорят, что рх "указывает" на х. Операция & применима только к переменным и элементам массива, конструкции вида &(х-1) и &3 являются незаконными. Нельзя также получить адрес регистровой переменной.
Унарная операция * рассматривает свой операнд как адрес конечной цели и обращается по этому адресу, чтобы извлечь содержимое. Следовательно, если y тоже имеет тип int, то
y= *рх;
присваивает y содержимое того, на что указывает рх. Так последовательность
рх = &х;
y= *рх;
присваивает y то же самое значение, что и оператор
y=x; //операция разыменования
переменные, участвующие во всем этом необходимо описать:
int x, y; int *px;
Итак: Если a - переменная, то &a - ее адрес в памяти.
Если p - указатель(адрес чего-то), *p - значение по этому адресу, которое можно читать и изменять.
|
Адрес |
Значение |
Указатель |
pnt |
*pnt |
переменная |
&var |
var |
В таблице всё относится к переменной и её адрес и значение.
Вы можете получить адрес и указателя:
p = &pnt;
В этом случае p - будет двойным указателем, который обычно объявляется следующим образом:
int **p = &pnt;
Получить значение к переменной var по двойному указателю можно, если произвести двойную операцию разыменования:
cout << **p << "\n";
Указатели могут входить в выражения. Например, если px указывает на целое x, то *px может появляться в любом контексте, где может встретиться x. Так оператор
y= *px+ 1
присваивает y значение, на 1 большее значения x;
printf("%d\n", *px)
печатает текущее значение x;
d=sqrt((double) *px)
получает в d квадратный корень из x, причем до передачи функции sqrt значение x преобразуется к типу double.
В выражениях вида
y= *px+ 1
унарные операции * и & связаны со своим операндом более крепко, чем арифметические операции, так что такое выражение берет то значение, на которое указывает px, прибавляет 1 и присваивает результат переменной y.
Ссылки на указатели могут появляться и в левой части присваиваний. Если px указывает на x, то
*px= 0
полагает x равным нулю, а
*px+= 1
увеличивает его на единицу, как и выражение
(*px)++
Круглые скобки в последнем примере необходимы; если их опустить, то поскольку унарные операции, подобные * и ++, выполняются справа налево, это выражение увеличит px, а не ту переменную, на которую он указывает.
И наконец, так как указатели являются переменными, то с ними можно обращаться, как и с остальными переменными. Если py - другой указатель на переменную типа int, то
py=px
копирует содержимое px в py, в результате чего py указывает на то же, что и px.
В чём польза указателей, представьте у вас в памяти сидит DVD-фильм и занимает область в несколько Гигабайт, вам нужно скопировать переменную с DVD-фильмом в функцию обработать и вернуть. Копировать DVD-фильм очень накладно, проще передать указатель на эту область памяти (указатель ничего не занимает, только место, в котором хранится адрес переменной) и обращаться к области памяти по указателю.