- •1. Роль указателей в языке с.
- •3. Определение указателя.
- •4. Объявление указателей.
- •5. Операции получения адреса и значения.
- •6. Правила использования основных операций.
- •7. Указатель на переменную и константу.
- •8. Инициализация указателей.
- •1. Присваивание указателю адреса существующего объекта:
- •9. Работа с указателями.
- •Int *pI;
- •Int I, *pI;
- •Int *pI;
- •Int I, *pI;
- •10. Задание, инициализация, вывод переменных и их указателей.
- •11. Ограничения на использование основных
- •12. Указатель константа.
- •13. Константы и ссылки/указатели
- •5 4 2 1 3 // Порядок интерпретации описания
- •16. Многоуровневая адресация
- •17. Операции над указателями.
- •18. Пустой указатель (null-указатель).
- •19. Ввод адреса с клавиатуры.
- •20. Разность значений указателей.
- •14. Присваивание указателей различного типа.
- •22. Явное преобразование типа указателя
- •23. Роль операции sizeof в управлении памятью
- •25. Работа с областью памяти переменного формата
25. Работа с областью памяти переменного формата
Иногда требуется организовать данные в памяти таким образом, что заранее неиз-вестна точная последовательность переменных различных типов - она определяется некоторым форматом. В этом случае требуется просматривать последовательно область памяти, извлекая из нее переменные разных типов. Такая задача может быть решена
с использованием нескольких указателей различного типа, которые сохраняют одинаковое значение (адрес) путем взаимного присваивания. Заметим, что операция *p++ примени-
тельно к любому указателю интерпретируется как "взять указуемую переменную и перейти к следующей", следовательно, значением указателя после выполнения операции будет адрес переменной, следующей за выбранной:
char *p, A[100], c;
int *q, i;
long *l r;
l = q = p = A; // назначить все указатели на
... // общий начальный адрес A
i = *q++; // взять целое по указателю
p = l = q; // выровнять значения всех
... // указателей
r = *l++; p = q = l;
c = *p++; q = l = p;
Более простой вариант заключается в использовании объединения (union), которое, как известно, позволяет использовать общую память для размещения своих элементов.
Если элементами union являются указатели, то операции присваивания можно исключить (соответствующий пример – функция printf :
union ptr
{ char *p;
int *q;
long *l; } PTR;
i = *(PTR.q)++; r = *(PTR.l)++; c = *(PTR.p)++;
Итак, что надо знать про указатели:
• указатель – это переменная, в которой записан адрес другой переменной;
• при объявлении указателя надо указать тип переменных, на которых он будет указывать, а перед именем поставить знак *;
• знак & перед именем переменной обозначает ее адрес;
• знак * перед указателем в рабочей части программы (не в объявле-нии) обозначает значение ячейки, на которую указывает указатель;
• нельзя записывать по указателю, который указывает непонятно куда –это вызывает сбой программы, поскольку что-то стирается в памяти;
• для обозначения недействительного указателя используется константа NULL;
• при изменении значения указателя на n он в самом деле сдвигается к n-ому следующему числу данного типа, то есть для указателей на целые числа на n*sizeof(int) байт;
• указатель печатаются по формату %p.
Теперь вам должно быть понятно, что многие функции ввода типа scanf и fscanf в самом деле принимают в параметрах адреса переменных, например
scanf ( "%d", &i);
Вопросы для самопроверки.
1. Роль указателей в языке С.
2. Назначение указателей.
3. Определение указателей.
4. Операции получения адреса и значения.
5. Инициализация ауказателя.
6. Многоуровенная адресация.
7. Ввод адреса с клавиатуры.
8. Пустой указатель.
9. Присваивание указателей различного типа.
10. Операция sizeof в указателях.
11. Указатель на void.