Покажчики в C: Що таке покажчик у програмуванні на C? Типи
⚡ Розумний підсумок
Вказівники в C – це змінні, які зберігають адресу пам'яті іншої змінної. Вони дозволяють динамічне виділення пам'яті, ефективну обробку масивів і рядків, а також складні структури даних, використовуючи оператори адреси та розіменування для читання або зміни значень.
Що таке покажчик у C?
A покажчик У мові C — це змінна, яка зберігає адресу іншої змінної. Вказівник також може посилатися на інший вказівник або на функцію. Вказівник можна збільшувати або зменшувати, щоб вказувати на наступну або попередню комірку пам'яті. Мета вказівника — заощадити місце в пам'яті та досягти швидшого часу виконання.
Як використовувати покажчики в C
Якщо ми оголошуємо змінну v типу int, v зберігає значення. Кожна змінна, окрім свого значення, також має адресу, тобто місце, де вона знаходиться в пам'яті. Адресу можна отримати, поставивши амперсанд (&) перед іменем змінної. Якщо вивести адресу змінної, вона виглядатиме як випадкове число, яке може відрізнятися від запуску до запуску.
Замість зберігання значення, вказівник зберігає адресу змінної. Наприклад:
int *y = &v;
| ЗМІННИЙ | Вказівник |
|---|---|
| A значення зберігається в названий адреса сховища/пам'яті. | A змінна Що вказує на адресу зберігання/пам’яті інший змінна. |
Оголошення покажчика
Як і змінні, покажчики в Програмування на C їх необхідно оголосити, перш ніж їх можна буде використовувати. Оголошення вказівника має таку форму:
data_type *pointer_variable_name;
Тут, тип даних — це базовий тип вказівника та вказує тип змінної, на яку вказує вказівник. Зірочка (*), той самий символ, що використовується для множення, — це оператор непрямості, який оголошує вказівник. Деякі коректні оголошення вказівників:
int *ptr_thing; /* pointer to an integer */ int *ptr1, thing; /* ptr1 points to an int; thing is an int */ double *ptr2; /* pointer to a double */ float *ptr3; /* pointer to a float */ char *ch1; /* pointer to a character */
Ініціалізація вказівника
Після оголошення вказівника ми ініціалізуємо його адресою змінної. Якщо вказівник неініціалізований та використовується, результати можуть бути непередбачуваними та потенційно катастрофічними. Щоб отримати адресу змінної, використовуйте оператор амперсанд (&) перед іменем змінної:
pointer = &variable;
Проста програма, яка ілюструє вказівник, наведена нижче:
#include <stdio.h> int main() { int a = 10; // variable declaration int *p; // pointer variable declaration p = &a; // store address of a in pointer p printf("Address stored in p is: %x\n", p); // access the address printf("Value stored in p is: %d\n", *p); // access the value return 0; }
вихід:
Address stored in p is: 60ff08 Value stored in p is: 10
| Operaтор | Сенс |
|---|---|
| * | Виконує дві функції: оголошує вказівник та повертає значення змінної, на яку посилаються (розіменування). |
| & | Виконує одну мету: повертає адресу змінної. |
Типи покажчиків у C
Нульовий покажчик
Ми створюємо нульовий покажчик, присвоївши йому значення NULL під час оголошення. Це корисно, коли покажчику ще не призначено адресу. Нульовий покажчик завжди містить значення 0:
#include <stdio.h> int main() { int *p = NULL; // null pointer printf("The value inside variable p is: %x", p); return 0; }
Покажчик пустоти
Вказівник типу void, який також називають узагальненим вказівником, не має жодного стандартного типу даних. Він створюється за допомогою ключового слова void і може зберігати адресу будь-якої змінної:
#include <stdio.h> int main() { void *p = NULL; // void pointer printf("The size of pointer is: %d\n", sizeof(p)); return 0; }
Дикий пойнтер
Вказівник називається диким вказівником, якщо він не ініціалізований нічим. Ці вказівники неефективні, оскільки вони можуть вказувати на невідому область пам'яті, що може спричинити проблеми та аварійне завершення роботи програми. Завжди будьте обережні з дикими вказівниками:
#include <stdio.h> int main() { int *p; // wild pointer printf("%d", *p); return 0; }
Інші типи вказівників у C включають висячий вказівник, комплексний вказівник, ближній вказівник, далекий вказівник та величезний вказівник.
Покажчики прямого та непрямого доступу
У мові C існує два еквівалентні способи доступу та маніпулювання вмістом змінної. Прямий доступ використовує ім'я змінної безпосередньо, тоді як непрямий доступ використовує вказівник на змінну:
#include <stdio.h> int var = 1; /* declare and initialize an int variable */ int *ptr; /* declare a pointer to int */ int main(void) { ptr = &var; /* point ptr to var */ printf("\nDirect access, var = %d", var); printf("\nIndirect access, var = %d", *ptr); *ptr = 48; /* change var through the pointer */ printf("\nIndirect access, var = %d", *ptr); return 0; }
Арифметика вказівника в C
Під час роботи з покажчиками дотримуйтесь цих правил пріоритету. Оператори * та & мають такий самий пріоритет, як і унарні оператори (заперечення !, інкремент ++, декремент –). В одному й тому ж виразі унарні оператори *, &, !, ++ та — обчислюються справа наліво. Якщо покажчик P вказує на змінну X, то *P можна використовувати скрізь, де можна записати X. Наступні вирази еквівалентні:
| вираз | Еквівалентний вираз |
|---|---|
| Y = *P + 1 | Y = X + 1 |
| *P = *P + 10 | Х = Х + 10 |
| *P += 2 | X + = 2 |
| +++П | ++X |
| (*P)++ | X++ |
В останньому випадку дужки потрібні: оскільки унарні оператори * та ++ обчислюються справа наліво, без дужок збільшуватиметься вказівник P, а не об'єкт, на який він вказує. Арифметичні операції, доступні над вказівниками, - це присвоєння, збільшення та зменшення, а також додавання або віднімання.tracвстановлюючи цілочисельне зміщення, яке переміщує вказівник на таку кількість елементів (кожен крок дорівнює розміру базового типу в байтах).
Вказівники та масиви в C з прикладами
Традиційно ми звертаємося до елементів масиву за допомогою індексу, але вказівники також спрощують цей процес. Вказівник, встановлений на ім'я масиву, вказує на перший елемент:
#include <stdio.h> int main() { int a[5] = {1, 2, 3, 4, 5}; // array initialization int *p; // pointer declaration p = a; // p points to the first element; same as &a[0] for (int i = 0; i < 5; i++) { printf("%d\n", *p); // print element p++; // move to the next element } return 0; }
Додавання числа до вказівника переміщує його на певну кількість елементів вперед. Якщо p вказує на комірку пам'яті 0, то p + 1 змушує вказівник вказувати на комірку пам'яті 1.
C Покажчики та рядки з прикладами
Рядок — це масив об'єктів типу char, що закінчуються нульовим символом '\0'. Ми можемо маніпулювати рядками за допомогою вказівників:
#include <stdio.h> #include <string.h> int main() { char str[] = "Hello Guru99!"; char *p; p = str; printf("First character is: %c\n", *p); p = p + 1; printf("Next character is: %c\n", *p); p = str; // reset the pointer for (int i = 0; i < strlen(str); i++) { printf("%c\n", *p); p++; } return 0; }
Інший спосіб роботи з рядками – це використання масиву вказівників:
#include <stdio.h> int main() { char *materials[] = {"iron", "copper", "gold"}; for (int i = 0; i < 3; i++) printf("%s\n", materials[i]); return 0; }
Переваги покажчиків у C
- Вказівники корисні для безпосереднього доступу до місць пам'яті.
- Вони забезпечують ефективний спосіб доступу до елементів масиву.
- Вони використовуються для динамічного розподілу та звільнення пам'яті.
- Вони використовуються для формування складних структур даних, таких як зв'язані списки, графіки та дерева.
Недоліки покажчиків у C
- Покажчики трохи складні для розуміння.
- Вони можуть спричиняти такі помилки, як помилки сегментації або доступ до небажаної ділянки пам'яті.
- Неправильне значення, надане вказівнику, може призвести до пошкодження пам'яті.
- Вказівники також відповідають за витоки пам'яті, якщо пам'ять не звільнена.
- Програміст зобов'язаний обережно поводитися з вказівником.

