Операции с указателями. Указатели и массивы

Кроме рассмотренных двух унарных операций * и &, с указателями можно выполнять следующие операции:

· сложение или вычитание указателя и целого числа, результат - указатель;

· увеличение или уменьшение переменной типа указатель, что эквивалентно прибавлению или вычитанию единицы;

· вычитание двух указателей, результат - целое число.

Прибавление к указателю p целого числа n означает увеличение адреса, который содержится в переменной p, на суммарный размер n элементов того типа, на который ссылается указатель. Другими словами значение указателя при прибавлении к нему целого числа n увеличивается на произведение n на количество байтов, занимаемое одним элементом того типа, на который ссылается указатель. Аналогичный смысл имеет вычитание целого числа n из указателя.

Разность двух указателей - это количество элементов данного типа, которое умещается между двумя адресами. Результатом вычитания указателей является целое число. Физически оно вычисляется как разность значений двух адресов, деленная на размер одного элемента заданного типа.

Отметим, что указатели нельзя складывать. В отличие от разности указателей, операция сложения указателей (т.е. сложения адресов памяти) не имеет смысла.

Напомним, что имя массива a является указателем на его первый элемент, т.е. выражения a и &(a[0]) эквивалентны. Для массива a операция сложения указателя a и целого числа n имеет смысл сдвига указателя a на n элементов вправо, если считать, что индексы элементов массива возрастают слева направо. Аналогично вычитание целого числа n из указателя a означает сдвиг указателя a влево на n элементов.

Учитывая арифметику указателей, получаем эквивалентность следующих выражений: a[i] и *(a+i). Действительно, при прибавлении к a целого числа i происходит сдвиг на i элементов вправо. Поскольку имя массива является адресом его начального элемента, получается адрес i-го элемента массива a. Применяя операцию звездочка *, получаем сам элемент a[i]. Точно так же эквивалентны выражения &(a[i]) и a+i.

Эта особенность арифметики указателей позволяет вообще не использовать квадратные скобки, т.е. обращение к элементу массива; вместо этого можно использовать указатели и операцию звездочка *.

Таким образом, выбор между массивами и указателями - это выбор между двумя эквивалентными способами записи программ. Указатели, возможно, нравятся системным программистам, которые привыкли к работе с адресами объектов. Массивы больше отвечают традиционному стилю.

Операция приведения типа

Операция приведения типа используется, когда значение одного типа преобразуется к другому типу. Операция обозначается именем типа, заключенным в круглые скобки; она записывается перед ее единственным аргументом.

Рассмотрим два примера. Пусть требуется преобразовать целое число к вещественному типу. В примере значение целой переменной n приводится к вещественному типу и присваивается вещественной переменной x:

double x;

int n;

. . .

x = (double) n; // Операция приведения к типу double

В данном случае никакой потери информации не происходит, поэтому такое приведение допустимо и по умолчанию:

x = n; // Эквивалентно x = (double) n;

Во следующем примере вещественное значение преобразуется к целому типу. При этом дробная часть вещественного числа отбрасывается, а знак числа сохраняется:

double x, y;

int n, k;

. . .

x = 3.7;

y = -1.5;

n = (int) x; // n присваивается значение 3

k = (int) y; // k присваивается значение -1

В результате выполнения операции приведения вещественного числа к целому типу происходит отбрасывание дробной части числа, т.е. потеря информации. Поэтому, если использовать операцию приведения типа неявно (т.е. в результате простого присваивания целой переменной вещественного значения), например,

double x; int n;

. . .

n = x; // неявное приведение вещественного типа к целому

то компилятор обязательно выдаст предупреждение или ошибку. Когда используется явное приведение типа, компилятору сообщается, что это не случайная ошибка, а намеренное приведение вещественного значения к целому типу, при котором дробная часть отбрасывается. При этом компилятор никаких предупреждений не выдает.

Операция приведения типа чаще всего используется для преобразования указателей (см. разд. 1.8).

Управляющие конструкции

Управляющие конструкции позволяют организовывать циклы и ветвления в программах. В Си всего несколько конструкций, причем многие из них можно не использовать т.к. они реализуются через остальные.

Фигурные скобки

Фигурные скобки позволяют объединить несколько простых (элементарных) операторов в один составной оператор, или блок. Во всех синтаксических конструкциях составной оператор можно использовать вместо простого.

Наши рекомендации