- •Ю.Е. Алексеев, а.В. Куров
- •Часть 4
- •Алексеев Юрий Евтихович Куров Андрей Владимирович
- •8. Символьный тип данных
- •8.1 Общие сведения и библиотечные функции
- •8.2 Примеры программ обработки символьных данных
- •8.3 Задания на обработку символьных матриц
- •9. Строки
- •9.1 Общие сведения и библиотечные функции
- •9.2 Примеры программ обработки строк (массивова символов)
- •9.3 Задания на обработку строк
- •10. Типы данных структура и объединение
- •10.1 Общие сведения о структурах
- •10.2 Примеры программ обработки структур
- •10.3 Задания на обработку структур
- •10.4 Объединения
- •10.5 Примеры программ обработки объединений
- •11. Файлы
- •11.1 Основные сведения о файлах
- •11.2 Библиотечные функции для работы с файлами
- •11.3 Примеры программ обработки текстовых файлов
- •11.4 Задания на обработку текстовых файлов.
- •11.5 Примеры программ обработки бинарных файлов
- •11.6 Задания на бинарные файлы.
- •12. Тип данных указатель
- •12.1 Общие сведения Объявления и присваивания
- •Операции с указателями
- •Приоритеты операций при работе с указателями.
- •Взаимосвязь массивов и указателей
- •12.2 Динамические переменные и массивы Динамические переменные
- •Динамические массивы
- •Двумерные динамические массивы
- •Доступ к элементам динамической матрицы
- •Библиотечные функции с для работы с динамическими переменными и массивами
- •Передача в функции динамических массивов
- •13 Динамические структуры данных
- •13.1 Списки Линейный список
- •Пример программы работы с однонаправленным списком
- •Пример программы работы с двунаправленным списком
- •13.2 Задания на обработку списков.
- •13.3 Деревья бинарные
- •Структура бинарного дерева
- •Примеры работ с бинарным деревом
- •Список литературы
- •Алфавитный указатель
- •Вопросы для самопроверки Символы
- •Структуры
- •Указатели
Приоритеты операций при работе с указателями.
Операции разадресации, инкремента, декремента и взятия адреса имеют одинаковый приоритет и выполняются справа налево. Рассмотрим примеры выполнения этих операций.
Пример 1. *++p – здесь сначала выполнится операция инкремент указателя (сложение значения с единицей, т.е. прибавление к его значению количества байт, отводимых для хранения данных того типа, с которым связан указатель), а затем будет получено содержимое памяти по новому адресу.
Пример 2. *p++ - в данном выражении сначала будет использовано значение переменной, хранящейся по адресу p, а затем указатель увеличится на величину, равную количеству байт, занимаемых значением типа, с которым связан указатель, т.к. инкремент является здесь постфиксным.
Пример 3. (*p)++ - в этом выражении значение переменной, хранящейся по адресу p, увеличится на единицу.
Пример 4. ++*p – в приведенном выражении производится сначала разадресация и полученное значение переменной, хранящейся по адресу p, увеличивается на единицу.
Пример 5. ++*++p – в данном выражении сначала увеличивается значение указателя на единицу, затем производится разадресация и полученное значение переменной, хранящейся по новому адресу, увеличивается на единицу.
Пример программы 1. Следующая программа иллюстрирует выполнение рассмотренных примеров.
#include "stdafx.h"
#include "conio.h"
int _tmain(int argc, _TCHAR* argv[])
{
float a[5];
float *p;
a[0]=7.7; a[1]=8.8;
a[2]=9.9; a[3]=10.8; a[4]=17.7;
p=a;
printf("a[0]=%6.2f *p=%6.2f p=%p",a[0],*p,p);
printf("\na[1]=%6.2f *++p=%6.2f ++p=%p adres [1]=%p", a[1],*++p,p,&a[1]);
printf("\na[1]=%6.2f ",a[1]);
(*p)++ ;
printf("\n (*p)++=%6.2f",*p);
++*p;
printf("\n ++*p=%6.2f",*p);
++*++p ;
printf("\n ++*++p=%6.2f",*p);
getch();
return 0;
}
Взаимосвязь массивов и указателей
В языке C существует очень тесная взаимосвязь между указателями и массивами. Любую операцию, выполняемую с помощью индексации массива, можно выполнить с применением указателей, причем в этом случае программа обычно работает быстрее [5]. В приведенной выше программе был объявлен массив float a[5]; и указатель на действительную величину float *p;. Поскольку имя массива в языке C есть не что иное, как адрес первого элемента массива, то присваивание p=a; означает, что указатель теперь хранит адрес первого элемента массива a. То же самое можно было выполнить и с помощью оператора присваивания p=&a[0]; Если выполнить оператор присваивания p+=i;, то указатель будет хранить адрес i-го элемнта, расположенного после p, в данном случае просто i-ого элемента массива a. Тогда выражение *(p+i) означает не что иное, как содержимое i-го элемента массива, т.е. a[i]. При вычислении выражения a[i] компилятор сам преобразует его в форму *(a+i), т.к. эти две формы являются тождественными. Если применить к этим двум выражениям адресную операцию & то можно получить также две тождественные записи: &a[i] и a+i. Указатель можно также использовать в выражениях с индексом: p[i] будет соответствовать записи *(p+i). Таким образом, выражение в виде обращения к элементу массива по индексу эквивалентно ссылке по указателю со смещением.
Однако есть и различие между именем массива и указателем. Укеазатель является переменной, поэтому операторы p=a; p++; допустимы, а операторы с именем массива, подобные приведенным, недопустимы: a=p; a++;
