Що таке вказівник на С?
Покажчик на С, являє собою змінну , яка зберігає адресу іншої змінної. Вказівник також може використовуватися для посилання на іншу функцію вказівника. Покажчик може бути збільшений / зменшений, тобто вказувати на наступне / попереднє місце в пам'яті. Призначення вказівника - заощадити місце в пам'яті та досягти більш швидкого часу виконання.
Як користуватися вказівниками в C
Якщо ми оголосимо змінну v типу int, v насправді збереже значення.
v дорівнює нулю зараз.
Однак кожна змінна, крім значення, також має свою адресу (або, простіше кажучи, де вона знаходиться в пам'яті). Адресу можна отримати, поставивши перед ім'ям змінної амперсанд (&).
Якщо ви надрукуєте адресу змінної на екрані, вона буде виглядати абсолютно випадковим числом (крім того, вона може відрізнятися від запуску до запуску).
Спробуємо це на практиці з покажчиком на прикладі C.
Результатом роботи цієї програми є -480613588.
Що таке покажчик? Замість того, щоб зберігати значення, покажчик буде зберігати адресу змінної.
Змінна покажчика
Int * y = & v;
ЗМІННИЙ |
Вказівник |
Значення зберігається в імені зберігання / адреса пам'яті |
Мінлива , що вказує на адресу зберігання / пам'яті інший змінної |
Оголошення покажчика
Як і змінні, покажчики в програмуванні на С повинні бути оголошені перед тим, як їх можна використовувати у вашій програмі. Покажчики можуть називатися як завгодно, якщо вони підкоряються правилам іменування C. Декларація покажчика має наступну форму.
data_type * pointer_variable_name;
Ось,
- data_type - це базовий тип вказівника типів змінних C і вказує на тип змінної, на яку вказує вказівник.
- Зірочка (*: та сама зірочка, яка використовується для множення), яка є оператором опосередкування, оголошує вказівник.
Давайте подивимося деякі допустимі декларації покажчиків у цьому посібнику з вказівників C:
int *ptr_thing; /* pointer to an integer */int *ptr1,thing;/* ptr1 is a pointer to type integer and thing is an integer variable */double *ptr2; /* pointer to a double */float *ptr3; /* pointer to a float */char *ch1 ; /* pointer to a character */float *ptr, variable;/*ptr is a pointer to type float and variable is an ordinary float variable */
Ініціалізуйте вказівник
Після оголошення вказівника ми ініціалізуємо його як стандартні змінні зі змінною адресою. Якщо покажчики в програмуванні на С не ініціалізовані та не використовуються в програмі, результати непередбачувані та потенційно згубні.
Щоб отримати адресу змінної, ми використовуємо оператор амперсанд (&), розміщений перед іменем змінної, адреса якої нам потрібна. Ініціалізація покажчика виконується з наступним синтаксисом.
Синтаксис покажчика
pointer = &variable;
Проста програма для ілюстрації вказівника наведена нижче:
#includeint main(){int a=10; //variable declarationint *p; //pointer variable declarationp=&a; //store address of variable a in pointer pprintf("Address stored in a variable p is:%x\n",p); //accessing the addressprintf("Value stored in a variable p is:%d\n",*p); //accessing the valuereturn 0;}
Вихід:
Address stored in a variable p is:60ff08Value stored in a variable p is:10
Оператор | Значення |
* | Обслуговує 2 цілі
|
& | Обслуговує лише одну мету
|
Типи вказівників на С
Нижче наведено різні типи покажчиків на мові C :
Нульовий покажчик
Ми можемо створити нульовий покажчик, призначивши нульове значення під час оголошення вказівника. Цей метод корисний, коли у вас не вказана адреса вказівника. Нульовий покажчик завжди містить значення 0.
Наступна програма ілюструє використання нульового вказівника:
#includeint main(){int *p = NULL; //null pointerprintf(“The value inside variable p is:\n%x”,p);return 0;}
Вихід:
The value inside variable p is:0
Порожній вказівник
У програмуванні на С порожній вказівник також називається загальним вказівником. Він не має жодного стандартного типу даних. Покажчик void створюється за допомогою ключового слова void. Він може використовуватися для зберігання адреси будь-якої змінної.
Наступна програма ілюструє використання покажчика void:
#includeint main(){void *p = NULL; //void pointerprintf("The size of pointer is:%d\n",sizeof(p));return 0;}
Вихід:
The size of pointer is:4
Дикий вказівник
Вказівник називається диким покажчиком, якщо він нічим не ініціалізований. Ці типи покажчиків C не ефективні, оскільки вони можуть вказувати на якесь невідоме місце в пам'яті, що може спричинити проблеми в нашій програмі, а це може призвести до збою програми. Завжди слід бути обережним під час роботи з дикими вказівниками.
Наступна програма ілюструє використання дикого вказівника:
#includeint main(){int *p; //wild pointerprintf("\n%d",*p);return 0;}
Вихідні дані
timeout: the monitored command dumped coresh: line 1: 95298 Segmentation fault timeout 10s main
Інші типи покажчиків на 'c' є наступними:
- Висячий вказівник
- Складний вказівник
- Біля вказівника
- Далекий вказівник
- Величезний вказівник
Вказівники на прямий та непрямий доступ
У C є два рівнозначні способи доступу до змінного вмісту та керування ним
- Прямий доступ: ми використовуємо безпосередньо ім’я змінної
- Непрямий доступ: ми використовуємо вказівник на змінну
Давайте зрозуміємо це за допомогою програми нижче
#include/* Declare and initialize an int variable */int var = 1;/* Declare a pointer to int */int *ptr;int main( void ){/* Initialize ptr to point to var */ptr = &var;/* Access var directly and indirectly */printf("\nDirect access, var = %d", var);printf("\nIndirect access, var = %d", *ptr);/* Display the address of var two ways */printf("\n\nThe address of var = %d", &var);printf("\nThe address of var = %d\n", ptr);/*change the content of var through the pointer*/*ptr=48;printf("\nIndirect access, var = %d", *ptr);return 0;}
Після компіляції програми без помилок результат:
Direct access, var = 1Indirect access, var = 1The address of var = 4202496The address of var = 4202496Indirect access, var = 48
Арифметика покажчика в C
Операції вказівника наведені на наступному малюнку
Пріоритетна операція (пріоритет)
Працюючи з покажчиками С, ми повинні дотримуватися наступних пріоритетних правил:
- Оператори * і & мають той самий пріоритет, що і одинарні оператори (заперечення !, приріст ++, декремент--).
- У цьому ж виразі одинарні оператори *, &,!, ++, - обчислюються справа наліво.
Якщо вказівник P вказує на змінну X, тоді * P можна використовувати скрізь, де можна записати X.
Наступні вирази еквівалентні:
int X = 10 int * P = & Y; Для наведеного вище коду наведені нижче вирази відповідають дійсності | |
Вираз | Еквівалентний вираз |
Y = * P + 1 * P = * P + 10 * P + = 2 ++ * P (* P) ++ | Y = X + 1 X = X + 10 X + = 2 ++ X X ++ |
В останньому випадку потрібні дужки: оскільки одинарні оператори * та ++ обчислюються справа наліво, без дужок збільшуватиметься вказівник P, а не об’єкт, на який вказує P.
Нижче в таблиці наведено арифметичну та основну операції, які можна використовувати при роботі з покажчиками на С
Операція | Пояснення |
Призначення | int * P1, * P2 P1 = P2; P1 і P2 вказують на одну і ту ж цілу змінну |
Інкрементація та декрементація | Int * P1; P1 ++; P1--; |
Додавання зміщення (Постійна) | Це дозволяє вказівнику переміщати N елементів у таблиці. Покажчик буде збільшено або зменшено в N разів за число байтів (типів) змінної. Р1 + 5; |
C Покажчики та масиви з прикладами
Традиційно ми отримуємо доступ до елементів масиву, використовуючи його індекс, але цей метод можна усунути за допомогою покажчиків. Покажчики полегшують доступ до кожного елемента масиву.
#includeint main(){int a[5]={1,2,3,4,5}; //array initializationint *p; //pointer declaration/*the ptr points to the first element of the array*/p=a; /*We can also type simply ptr==&a[0] */printf("Printing the array elements using pointer\n");for(int i=0;i<5;i++) //loop for traversing array elements{printf("\n%x",*p); //printing array elementsp++; //incrementing to the next element, you can also write p=p+1}return 0;}
Вихідні дані
12345
Додавання певного числа до покажчика перемістить розташування покажчика до значення, отриманого за допомогою операції додавання. Припустимо, p є покажчиком, який в даний час вказує на місце в пам'яті 0, якщо ми виконуємо наступну операцію додавання, p + 1, тоді він буде виконуватися таким чином:
Оскільки p в даний час вказує на розташування 0 після додавання 1, значення стане 1, а отже, вказівник вказуватиме на розташування в пам'яті 1.
C Покажчики та рядки з прикладами
Рядок - це масив об'єктів char, що закінчується нульовим символом '\ 0'. Ми можемо маніпулювати рядками за допомогою покажчиків. Цей покажчик у прикладі C пояснює цей розділ
#include#include 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);printf("Printing all the characters in a string\n");p=str; //reset the pointerfor(int i=0;i Вихідні дані
First character is:HNext character is:ePrinting all the characters in a stringHelloGuru99!Інший спосіб обробки рядків - це масив покажчиків, як у наступній програмі:
#includeint main(){char *materials[ ] = { "iron", "copper", "gold"};printf("Please remember these materials :\n");int i ;for (i = 0; i < 3; i++) {printf("%s\n", materials[ i ]);}return 0;} Вихід:
Please remember these materials:ironcoppergoldПереваги покажчиків в C
- Покажчики корисні для доступу до місць пам'яті.
- Покажчики забезпечують ефективний спосіб доступу до елементів масивної структури.
- Покажчики використовуються для динамічного розподілу пам'яті, а також для звільнення.
- Покажчики використовуються для формування складних структур даних, таких як пов'язаний список, графік, дерево тощо.
Недоліки покажчиків на C
- Вказівники трохи складні для розуміння.
- Покажчики можуть призвести до різних помилок, таких як помилки сегментації, або отримати доступ до місця пам'яті, яке взагалі не потрібно.
- Якщо вказівник подає неправильне значення, це може спричинити пошкодження пам'яті.
- Вказівники також відповідають за витік пам'яті.
- Покажчики порівняно повільніші за показники змінних.
- Програмістам дуже важко працювати з покажчиками; тому відповідальність програміста - ретельно маніпулювати покажчиком.
Резюме
- Покажчик - це не що інше, як місце в пам'яті, де зберігаються дані.
- Вказівник використовується для доступу до місця пам'яті.
- Існують різні типи покажчиків, такі як нульовий покажчик, дикий покажчик, порожній покажчик та інші типи покажчиків.
- Покажчики можна використовувати з масивом і рядком для більш ефективного доступу до елементів.
- Ми можемо створити покажчики на функції для динамічного виклику функції.
- Арифметичні операції можна виконувати над покажчиком, який відомий як арифметика покажчика.
- Вказівники також можуть вказувати на функції, що полегшує виклик різних функцій у випадку визначення масиву покажчиків.
- Коли ви хочете мати справу з різними типами даних змінної, ви можете використовувати покажчик порожнечі typecast.