- •Введение
- •Изучение среды программирования
- •Теоретические сведения
- •Среда программирования
- •Задание к работе
- •Содержание отчета
- •Контрольные вопросы
- •Переменные и операции над ними
- •Теоретические сведения
- •Основные определения
- •Операции над целыми числами
- •Вещественные числа и операции над ними
- •Задание к работе
- •Содержание отчета
- •Контрольные вопросы
- •Конструкция выбора, логические и другие операции
- •Теоретические сведения
- •Конструкция выбора и составная инструкция
- •Операторы отношения и логические операторы
- •Остальные операторы
- •Задание к работе
- •Содержание отчета
- •Контрольные вопросы
- •Конструкции циклов
- •Теоретические сведения
- •Цикл while
- •Цикл for
- •Конструкция в конструкции
- •Задание к работе
- •Свойства массивов
- •Структуры
- •Задание к работе
- •Операции с указателями
- •Указатели и массивы
- •Указатели и структуры
- •Задание к работе
- •Использование указателей для передачи результата и аргумента
- •Задание к работе
- •Содержание отчета
- •Контрольные вопросы
- •Библиографический список
- •644046, Г. Омск, пр. Маркса, 35в
-
Операции с указателями
Основные операции над указателями это присваивание и разыменование.
Операция присваивания записывает в указатель адрес какого-то объекта в памяти. Для того, чтобы узнать адрес какого-либо объекта, используется оператор взятия адреса – «&». Например, чтобы присвоить указателю p адрес переменной a нужно записать:
p = &a.
Обратная операция называется операцией разыменования. Результатом этой операции является переменная, которая хранилась по адресу, на который ссылался указатель. Эта операция указывается с помощью оператора «*». Например, следующий код запишет в переменную a число 1:
p = &a;
*p = 1;
А следующее выражение увеличит значение переменной a на 1:
(*p)++;
Операция разыменования имеет приоритет выше, чем арифметические операторы, поэтому пришлось поставить скобки, чтобы сначала была выполнена операция разыменования, а только потом инкрементирование.
Над указателями можно выполнять и арифметические действия сложения и вычитания (а также инкремента и декремента). Рассмотрим следующий фрагмент кода:
int a[]={0,1,2,3,4};
int b;
int* p = &a[2];
p++;
b=*p;
Чему будет равно значение b после его выполнения?
В третьей строке в указатель p был записан адрес элемента a[2].
В четвертой строке этот адрес должен быть увеличен на 1. В С при прибавлении к указателю 1 он увеличивается таким образом, чтобы указывать на следующий в памяти элемент соответствующего типа. Например, если переменная целого типа занимает 4 байта, то адрес, хранящийся в указателе, увеличивается на 4. В пример, после увеличения на 1 указатель будет указывать на следующий элемент массива, т.е. на a[3].
В результате операции в последней строке в b будет записано число 3.
В общем случае, при прибавлении к указателю числа x, он увеличивается на число, равное произведению x на количество байт, которые занимает тип указателя. Другими словами, указатель как бы сдвигается на соответствующее число элементов в массиве.
Аналогичным образом определена операция вычитания из указателя, только указатель уменьшается, или сдвигается в сторону начала массива.
Операции, при которых вычисляется адрес, называются адресной арифметикой. Они позволяют очень эффективно работать с расположенными в памяти массивами и структурами данных. Однако, как и операция индексирования, требуют особой осторожности, поскольку запись по неверно вычисленному адресу может привести к зависанию программы и даже всей операционной системы.
-
Указатели и массивы
Операция индексирования, по сути, также является операцией адресной арифметики. Можно записать следующее равенство: a[i]=a+i. Фактически, имя массива a является указателем на начало массива. Однако, в отличие от обычных указателей, адрес массива определяется во время компиляции и не изменяется во время выполнения программы.
Сравним два объявления:
int a[10];
int *p;
В первом случае компилятор отведет в памяти место под 10 переменных целого типа и запомнит адрес нулевого элемента. Этот адрес он будет подставлять как константу во все выражения, где встретиться переменная a.
Во втором случае компилятор выделит в памяти место под хранение одного адреса. Во все выражения, где встретится переменная p, он будет подставлять операции, которые или берут из памяти или записывают в память по адресу переменной p адрес, над которым выполняются действия.
За исключением сказанного, указатель и массив схожи. Можно в указатель переписать указатель на массив: p=a. Обратите внимания, операция взятия адреса тут не требуется. Над массивом можно выполнять адресные операции (которые не изменяют указатель над массив), а над указателем можно выполнять операцию индексирования.