- •Основы алгоритмизации и программирования, язык Си
- •Введение
- •Блок-схема алгоритма Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Операции и выражения
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора Директива #include
- •Директива #define
- •Понятие пустого и составного операторов
- •Условные операторы
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Операторы перехода (break, continue, return, goto)
- •Примеры программ
- •Массивы Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Параметры по умолчанию
- •Передача массива в функцию
- •Inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Доступ к элементам структуры
- •Инициализация структур
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Примеры программ
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Потоки и файлы
- •Файлы Основные сведения о файловой системе
- •Организация посимвольного ввода и вывода
- •Определение конца файла feof()
- •Организация ввода и вывода строк
- •Удаление файлов
- •Дозапись потока
- •Позиционирование в файле
- •Текстовые и двоичные файлы
- •Функции fread() и fwrite()
- •Примеры программ
- •Хеширование
- •Схемы хеширования
- •Метод открытой адресации с линейным опробыванием
- •Метод цепочек
- •Машинное представление графов
- •Примеры программ
- •Литература
Операции с указателями
Указатели могут встречаться в выражениях. То есть если p - указатель на объект некоторого типа, то он может использоваться в выражении наряду с другими указателями, а также переменными и константами, не являющимися указателями, например:
*p=-2;
*p/=i-1;
(*p)--;
В первом выражении значение -2 заносится в ячейку памяти по адресу p, во втором выражении это значение уменьшается в i-1 раз, в третьем - уменьшается на единицу. В третьем выражении использованы скобки, так как операции с одинаковым приоритетом выполняются справа налево, таким образом *p-- уменьшит адрес.
Указатели могут использоваться в качестве операндов в арифметических выражениях. Так, например, если p - указатель, то p++ является адресом следующего элемента. Следовательно, конструкция p+n (p - указатель, n - целое число) задает адрес n-го элемента, на который указывает указатель p+n.
Между адресами могут быть выполнены операции сравнения. Так же любой адрес может быть проверен на равенство (==) или неравенство (!=) со специальным значением NULL. NULL определяет указатель, который ничего не адресует.
include <stdio.h>
void main(void) /*демонстрация объявления указателей*/
{ int *p,i; /* на объект типа int */
scanf("%d",&i);
p=&i; /* теперь р содержит адрес переменной i*/
printf("\ni=%d",i); /* печать значения переменной i */
printf("\n*p=%d",*p); /* печать значения по адресу p*/
}
К указателю типа void* применяются следующие операции:
= , == , != , > , < , <= , >=
Связь между указателями и массивами
В С(С++) между индексированием и адресацией существует тесная взаимосвязь. Доступ к элементам массива с помощью индексирования может быть заменен доступом к ним с использованием адресов. При этом второй вид доступа выполняется быстрее. Взаимосвязь указателей и массивов хорошо видна из приводимого ниже рисунка 9.
Выражение вида y=&a[0] присваивает переменной y адрес элемента a[0].
Выражение y+1 указывает на следующий элемент массива, при этом учитывается масштабирование, то есть выполняется приращение адреса с учетом
int a[10]; int *y;
X=a[0] |
a |
a[0] |
y |
X=*y |
X=a[1] |
a+1 |
a[1] |
y+1 |
X=*(y+1) |
|
|
. . . |
|
|
X=a[9] |
a+9 |
a[9] |
y+9 |
X=*(y+9) |
Рис. 9. Связь указателей и массивов
размеров памяти отводимой, под элемент. Так как имя массива является адресом его нулевого элемента, то выражение y=&a[0] может быть записано иначе y=a. Доступ к i-му элементу массива может быть осуществлен либо, используя имя массива a[i] и *(a+i), либо указатель *y и *(y+i). Наряду со сходством имени массива и указателей между ними существует различие. Указатель - это переменная и выражения вида y=a и y++ являются допустимыми. Имя массива - константа и выражения a=y, a++, y=&a являются ошибочными, так как значение константы не может быть изменено.