
- •Робота з вказівниками
- •Теоретичні відомості Масиви
- •Теоретичні відомості Вказівники Поняття про вказівники
- •Оператори для роботи з вказівниками.
- •Вирази з вказівниками
- •Присвоєння вказівників.
- •Арифметичні дії з вказівниками
- •Порівняння вказівників
- •Динамічне виділення і вказівники
- •Вказівники на константи
- •Вказівники і масиви
- •Вказівники на символьні масиви
- •Масиви вказівників
- •Вказівники на вказівники
- •Завдання
- •Вказівники
Вказівники і масиви
Масиви і вказівники тісно пов’язані між собою. Розглянемо такий фрагмент:
сhar str[80], *p1; p1 = str;
тут р1 вказує на перший елемент масиву str. Якщо необхідно отримати доступ до п’ятого елемента str, то необхідно записати:
str[4], або *(p1+4)
Обидва оператори повертають п’ятий елемент.
С має два методи доступу до елементів масиву. Це важливо, тому що арифметичні дії над вказівниками можуть виконуватися швидше ніж індексація масиву. Оскільки швидкість роботи програми часто є важливим чинником, використання вказівників для доступу до елементів є типовим для С. Порівняйте два варіанти стандартної бібліотечної функції puts() для демонстрації цих методів.
Використання масиву |
Використання вказівників |
int puts(const char *s) { register int i; for(t=0; s[t]; ++t)putchar(s[t]); return 1; } |
int puts(const char *s) { while(*s) putchar(*s++); return 1; } |
Професійні програмісти віддадуть перевагу версії з вказівниками при написанні програм. Фактично, версія з вказівником демонструє типовий спосіб написання програм на С.
Вказівники на символьні масиви
Багато рядкових операцій в С виконується за допомогою вказівників, оскільки доступ до рядків здійснюється послідовно.
Наприклад, тут показана версія із стандартної бібіліотеки функції strcmp(), в якій використовуються вказівники:
//Використання вказівників
int strcmp(const char *s1, const char *s2)
{
while(*s1)
if(*s1-*s2)
return *s1-*s2;
else {
s1++;
s2++;
}
return 0; //рівність
}
Треба пам’ятати, що всі рядки в С закінчуються нульовим символом, який інтерпретується як false ("неправда"). Тоді оператор
while (*s1)
видає "істину", поки не досягне кінця рядка, strcmp() повертає нуль, якщо s1 = s2. Вона повертає число, менше 0, якщо s1 < s2.
Масиви вказівників
Можна створювати масиви вказівників. Для оголошення масиву цілочисельних вказівників з десяти елементів слід написати
int *x[10];
Для присвоєння адреси цілочисельної змінної Срр третьому елементу масиву слід написати:
x[2] = &Cpp;
для отримання значення цілочисельної змінної Срр слід написати:
*x[2];
Якщо необхідно передати масив вказівників у функцію, можна використати метод, аналогічний передачі звичайних масивів. Просто потрібно викликати функцію з іменем масиву без індексів. Наприклад, функція, яка отримує масив х повинна виглядати так:
void display_array(int *q[])
{
int t;
for(t=0; t<10; t++)
printf("%d",*q[t]);
}
Необхідно пам’ятати, що q – це не вказівник на ціле, а масив вказівників на цілі. Отже, q – необхідно оголосити як масив цілих вказівників. Його не можна оголосити як простий цілочисельний вказівник, бо він ним і не є.
Вказівники на вказівники
У випадку вказівників на змінні, вказівник містить адресу деякої ділянки пам’яті, яка містить деяке значення. У випадку вказівника на вказівник, перший вказівник містить адресу другого вказівника, який в свою чергу містить адресу комірки пам’яті, в якій міститься деяке значення.
Загальний синтаксис для оголошення вказівника на вказівник:
type** PointerToPoinetrName;
Приклади оголошення, ініціалізації і використання вказівників на вказівники.
int nNum = 1;
int* pnNum = &nNum;
int ** ppnNum = &pnNum;
cout << nNum << "\n";
// виводить 1, використовуючи змінну nNum
cout << *pnNum << "\n";
/* виводить 1, використовуючи змінну pnNum */
cout << **ppnNum << "\n";
/* виводить 1, використовуючи вказівник на вказівник*/
Обмеження на ініціалізацію вказівника на вказівник: С++ не дозволяє два рази застосовувати оператор звертання за адресою & для присвоєння вказівнику на вказівник адреси вказівника на змінну. Наприклад, такий запис компілятором не сприймається:
int nNum = 1; int **ppnNum = &&nNum;