Указатели в C: Какво е указател в програмирането на C? Видове
Какво е показалец в C?
- Показалка в C, е променлива, която съхранява адреса на друга променлива. Указател може да се използва и за препратка към друга функция на указател. Указателят може да се увеличава/намалява, т.е. да сочи към следващото/предишното място в паметта. Целта на показалеца е да спести място в паметта и да постигне по-бързо време за изпълнение.
Как да използвате указатели в C
Ако декларираме променлива v от тип int, v действително ще съхранява стойност.
v сега е равно на нула.
Всяка променлива обаче освен стойност има и свой адрес (или по-просто казано къде се намира в паметта). Адресът може да бъде извлечен чрез поставяне на амперсанд (&) преди името на променливата.
Ако отпечатате адреса на променлива на екрана, той ще изглежда като напълно произволно число (още повече, че може да е различно от изпълнение до изпълнение).
Нека опитаме това на практика с указател в C пример
Резултатът от тази програма е -480613588.
Сега, какво е указател? Вместо да съхранява стойност, указателят ще съхранява адреса на променлива.
Променлива показалец
Int *y = &v;
Променлива | УКАЗАТЕЛ |
---|---|
A стойност съхранявани в a на име адрес за съхранение/памет | A променлив че сочи към адреса за съхранение/памет на още променлив |
Деклариране на указател
Подобно на променливите, указателите в C програмиране трябва да бъдат декларирани, преди да могат да бъдат използвани във вашата програма. Указателите могат да се наименуват както искате, стига да се подчиняват на правилата за именуване на C. Декларацията на указател има следната форма.
data_type * pointer_variable_name;
Тук
- тип_данни е основният тип на указателя от типовете променливи на 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 */
Инициализирайте указател
След като декларираме указател, ние го инициализираме като стандартни променливи с адрес на променлива. Ако указателите в C програмирането са неинициализирани и използвани в програма, резултатите могат да бъдат непредвидими и потенциално катастрофални.
За да получим адреса на променлива, използваме оператора амперсанд (&), поставен преди името на променлива, чийто адрес ни е необходим. Инициализацията на указателя се извършва със следния синтаксис.
Синтаксис на показалеца
pointer = &variable;
По-долу е дадена проста програма за илюстриране на указател:
#include <stdio.h> int main() { int a=10; //variable declaration int *p; //pointer variable declaration p=&a; //store address of variable a in pointer p printf("Address stored in a variable p is:%x\n",p); //accessing the address printf("Value stored in a variable p is:%d\n",*p); //accessing the value return 0; }
Изход:
Address stored in a variable p is:60ff08 Value stored in a variable p is:10
OperaTor | Значение |
---|---|
* | Служи за 2 цели
|
& | Служи само за 1 цел
|
Видове указатели в C
Следват различните Видове указатели в C:
Нулев указател
Можем да създадем нулев указател, като присвоим нулева стойност по време на декларацията на указателя. Този метод е полезен, когато нямате присвоен адрес на показалеца. Нулевият указател винаги съдържа стойност 0.
Следната програма илюстрира използването на нулев указател:
#include <stdio.h> int main() { int *p = NULL; //null pointer printf(“The value inside variable p is:\n%x”,p); return 0; }
Изход:
The value inside variable p is: 0
Показалец за празнота
In C програмиране, празен указател се нарича още общ указател. Той няма стандартен тип данни. Празен указател се създава с помощта на ключовата дума void. Може да се използва за съхраняване на адрес на всяка променлива.
Следващата програма илюстрира използването на празен указател:
#include <stdio.h> int main() { void *p = NULL; //void pointer printf("The size of pointer is:%d\n",sizeof(p)); return 0; }
Изход:
The size of pointer is:4
Див показалец
За указател се казва, че е див указател, ако не се инициализира към нищо. Тези типове C указатели не са ефективни, защото могат да сочат към някакво неизвестно място в паметта, което може да причини проблеми в нашата програма и може да доведе до срив на програмата. Човек винаги трябва да бъде внимателен, когато работи с диви указатели.
Следващата програма илюстрира използването на див указател:
#include <stdio.h> int main() { int *p; //wild pointer printf("\n%d",*p); return 0; }
Изход:
timeout: the monitored command dumped core sh: line 1: 95298 Segmentation fault timeout 10s main
Други типове указатели в 'c' са както следва:
- Висяща показалка
- Комплексен показалец
- Близо до показалеца
- Далечен показалец
- Огромен показалец
Указатели за директен и индиректен достъп
В C има два еквивалентни начина за достъп и манипулиране на променливо съдържание
- Директен достъп: използваме директно името на променливата
- Индиректен достъп: използваме указател към променливата
Нека разберем това с помощта на програмата по-долу
#include <stdio.h> /* 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 = 1 Indirect access, var = 1 The address of var = 4202496 The address of var = 4202496 Indirect access, var = 48
Аритметика на указателя в C
Операциите с показалеца са обобщени на следващата фигура
Приоритетна операция (приоритет)
Когато работим с C указатели, трябва да спазваме следните правила за приоритет:
- Операторите * и & имат същия приоритет като унарните оператори (отрицание!, инкрементация++, декремент–).
- В същия израз унарните оператори *, &,!, ++, – се изчисляват отдясно наляво.
Ако P указател сочи към X променлива, тогава * P може да се използва навсякъде, където X може да бъде написано.
Следните изрази са еквивалентни:
int X =10 int *P = &Y; For the above code, below expressions are true
Изразяване | Еквивалентен израз |
---|---|
Y=*P+1
*P=*P+10 *P+=2 +++P (*P)++ |
Y=X+1
X=X+10 X+=2 ++X X++ |
В последния случай са необходими скоби: тъй като унарните оператори * и ++ се изчисляват отдясно наляво, без скобите би се увеличил указателят P, а не обектът, към който P сочи.
Таблицата по-долу показва аритметичните и основните операции, които могат да се използват при работа с C указатели
OperaАЦИ | Обяснение |
---|---|
Задание | int *P1,*P2 P1=P2; P1 и P2 сочат към една и съща целочислена променлива |
Увеличаване и намаляване | Int *P1; P1++;P1– ; |
Добавяне на отместване (константа) | Това позволява на показалеца да премести N елемента в таблица. Указателят ще бъде увеличен или намален с N пъти броя на байтовете от типа на променливата. P1+5; |
C указатели и масиви с примери
Традиционно ние осъществяваме достъп до елементите на масива, използвайки неговия индекс, но този метод може да бъде елиминиран чрез използване на указатели. Указателите улесняват достъпа до всеки елемент от масива.
#include <stdio.h> int main() { int a[5]={1,2,3,4,5}; //array initialization int *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 elements p++; //incrementing to the next element, you can also write p=p+1 } return 0; }
Изход:
1 2 3 4 5
Добавянето на определено число към указател ще премести местоположението на указателя до стойността, получена чрез операция на добавяне. Да предположим, че p е указател, който в момента сочи към местоположението на паметта 0, ако извършим следната операция за събиране, p+1, тогава тя ще се изпълни по този начин:
Тъй като p в момента сочи към местоположението 0 след добавяне на 1, стойността ще стане 1 и следователно указателят ще сочи към местоположението в паметта 1.
C указатели и низове с примери
Низът е масив от char обекти, завършващ с нулев знак '\ 0'. Можем да манипулираме низове с помощта на указатели. Този указател в примера на C обяснява този раздел
#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); printf("Printing all the characters in a string\n"); p=str; //reset the pointer for(int i=0;i<strlen(str);i++) { printf("%c\n",*p); p++; } return 0; }
Изход:
First character is:H Next character is:e Printing all the characters in a string H e l l o G u r u 9 9 !
Друг начин за обработка на низове е с масив от указатели като в следната програма:
#include <stdio.h> int 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: iron copper gold
Предимства на указателите в C
- Указателите са полезни за достъп до места в паметта.
- Указателите осигуряват ефективен начин за достъп до елементите на масивна структура.
- Указателите се използват за динамично разпределение на паметта, както и за освобождаване.
- Указателите се използват за формиране на сложни структури от данни като свързан списък, графика, дърво и др.
Недостатъци на указателите в C
- Указателите са малко сложни за разбиране.
- Указателите могат да доведат до различни грешки като грешки в сегментирането или да имат достъп до място в паметта, което изобщо не е необходимо.
- Ако на указател е предоставена неправилна стойност, това може да причини повреда на паметта.
- Указателите също са отговорни за изтичането на памет.
- Указателите са сравнително по-бавни от тези на променливите.
- За програмистите е много трудно да работят с указателите; следователно е отговорност на програмиста да манипулира внимателно указател.
Oбобщение
- Указателят не е нищо друго освен място в паметта, където се съхраняват данни.
- За достъп до местоположението на паметта се използва указател.
- Има различни видове указатели, като нулев указател, уайлд указател, празен указател и други видове указатели.
- Указателите могат да се използват с масив и низ за по-ефективен достъп до елементите.
- Можем да създадем функционални указатели, за да извикаме функция динамично.
- Аритметичните операции могат да се извършват върху указател, който е известен като аритметика на указател.
- Указателите също могат да сочат към функция, което улеснява извикването на различни функции в случай на дефиниране на масив от указатели.
- Когато искате да работите с различен тип променливи данни, можете да използвате празен указател типcast.