- •Вопросы к экзамену по дисциплине
- •6. Типы данных: целый, вещественный, символьный. Размеры данных.
- •7.Правила определения переменных в программе. Инициализация переменных.
- •10.Операции сдвига.
- •11.Операции отношения, логические операции.
- •Int I, j, k;
- •15.Приоритет операций и порядок вычисления выражений.
- •16.Функция форматированного вывода printf.
- •18.Операторы преобразования данных и операторы управления. Оператор простой и составной, блок.
- •(Последовательно выполняемые операторы)
- •19.Виды управляющих конструкций программы.
- •20.Операторы ветвления, условный оператор.
- •21.Оператор переключения(Switch).
- •22.Оператор цикла с заданным числом повторений.
- •23.Оператор цикла с предусловием.
- •24.Оператор цикла с постусловием.
- •25.Операторы прерывания и продолжения цикла.
- •26.Одномерные и многомерные массивы, их инициализация.
- •27.Указатели. Связь между указателями и массивами.
- •28.Операции над указателями и массивами.
- •29.Операции взятия адреса, обращения по адресу.
- •30.Определение функции. Возвращение значения: оператор return. Описание функции, вызов функции.
- •31.Аргументы функции: формальные и фактические. Передача аргументов, стек.
- •32.Рекурсивные программы.
- •33.Функции для работы со строками: сравнение, копирование.
- •47. Функции для работы со строками: поиск в строке.
- •34.Функции для работы со строками: преобразование форматов.
- •35.Локальные и глобальные переменные.
- •36.Классы памяти. Автоматические переменные. Внешние и статические переменные.
- •37. Декларация структур.
- •38. Инициализация и доступ к элементам структуры.
- •39. Вложенные структуры и массивы структур.
- •40. Указатели на структуры.
- •41.Файлы.Функции работы с указателем текущей позиции файла.
- •43.Функция чтения и записи в файл в построчном режиме.
- •44.Функция чтения и записи в файл в посимвольном режиме.
- •45.Функция чтения и записи двоичных файлов.
- •46.Списки.Операции над списками. Односвязные и двусвязные списки.
- •47.Реализация списка на основе массива структур.
- •48.Реализация списка на основе массива данных.
- •49.Очереди. Операции над очередями.
- •50.Реализация очереди на основе массива.
- •51.Стеки. Операции над стеками.
- •52.Реализация стека на основе массива.
- •53.Сортировка методом обмена(пузырька).
- •Анализ пузырьковой сортировки. Пузырьковая сортировка обладает несколькими характеристиками:
- •54.Методом выбора.
- •55.Методом вставки.
- •56.Методом Шелла.
- •57.Метод быстрой сортировки(Хоара).
28.Операции над указателями и массивами.
Элементы одного массива хранятся в памяти подряд, поэтому адрес каждого последующего элемента больше адреса предыдущего на размер одного элемента, т.е на sizeof(тип)байт, гдетип - тип элемента массива. Поэтому, зная адрес одного элемента, легко вычислить адрес другого.
В языке С программист имеет возможность воспользоваться этим с помощью арифметических операций с указателями,т.е. прибавлением к ним (или вычитанием из них) целой величины:
p+i
p-i
p+=i
p-=i
p++
p--
где: p - указатель, i - целочисленное выражение.
Допускается также вычитание указателей:
p1-p2
где p1, p2 - указатели. Результатом вычитания является целое число.
Чтобы программист не был вынужден при этом каждый раз учитывать размер элемента, в языке Си принято правило: все арифметические операции с указателями выполняются в единицах памяти того типа объекта, на который ссылается этот указатель. Иными словами, операцияp++ означает реальное увеличениеpне на единицу, а на sizeof(*p) ; при этомpкак раз будет указывать на следующий элемент массива. Аналогично, выражениеp+iозначает в действительностиp+ i*sizeof(*p) , т.е. смещение наiэлементов.
Заметим, что из-за этого указатели на объекты разных типов, первоначально равные, могут стать неравными при прибавлении к ним одной и той же величины:
int a[5], *q=a; // i указывает на a[0]
double*d=(double*)q;
// Теперь d=q(не считая разницы в типах)
q++;d++;
// теперь d>q, т.к. хранимый вdадрес
// увеличился на 8, а хранимый в q- на 4
q++; // а теперь сноваd=q, и равно &a[2]
Однако на практике подобная адресация одного и того же участка памяти указателями разных типов редко имеет смысл.
В силу сказанного выше, адрес i-го элемента массиваAвсегда можно записывать и как &A[i], и какA+i. Итак, для массивов записьA[i] и *(A+i) эквивалентна. Для удобства операций с указателями, в языке С введено такое же правило записи и для них:
p[i] равносильно *(p+i)
где p - указатель, i - целочисленное выражение.
Иными словами, для обращения к i-му (считая от места, куда указываетp) элементу массива вместо записи *(p+i) можно писать короче:p[i]. Соответственно, и для указателей, и для массивов запись *pэквивалентнаp[0]
Пример:
inta[5], *q=a; // Инициализацияq:qуказывает наa[0]
//(Здесь * перед qозначает объявление его типа(указатель), а не разадресацию)
q++;
*q=40; // Означаетa[1]=40;
q[3]=70; // Означаетa[4]=70;
q[-1]=22; // Означаетa[0]=22;
Операции с указателями бывают особенно полезны для массивов char. (Напомним, что в любом месте, где допустима строка как массивchar, допустим также указатель наchar). С их помощью можно, например, обратиться к середине строки:
chars[]="Hello,world!";
cout<<s+7; // Будет выведен текст:world!
При сравнении указателей могут использоваться отношения любого вида (">", ">=", "<", "<=", "==", "!="). Наиболее важными видами проверок являются отношения равенства или неравенства. Остальные отношения порядка имеют смысл только для указателей на последовательно размещенные объекты (элементы одного массива).
Разность двух указателей дает число объектов адресуемого ими типа в соответствующем диапазоне адресов. Очевидно, что уменьшаемый и вычитаемый указатель также должны соответствовать одному массиву, иначе результат операции не имеет практической ценности.
Любой указатель можно сравнивать со значением NULL, которое означает недействительный адрес. Значение NULL можно присваивать указателю как признак пустого указателя. NULL заменяется препроцессором на выражение (void *)0.