Wskaźniki w C: Co to jest wskaźnik w programowaniu C? Typy

Co to jest wskaźnik w C?

Kolekcja Wskaźnik w C jest zmienną przechowującą adres innej zmiennej. Wskaźnika można także używać do odwoływania się do innej funkcji wskaźnika. Wskaźnik można zwiększać/zmniejszać, tj. wskazywać następną/poprzednią komórkę pamięci. Celem wskaźnika jest zaoszczędzenie miejsca w pamięci i osiągnięcie szybszego czasu wykonania.

Jak używać wskaźników w C

Jeśli zadeklarujemy zmienną v typu int, v faktycznie przechowa wartość.

Jak używać wskaźników w C

v jest teraz równe zero.

Jednak każda zmienna oprócz wartości ma także swój adres (czyli najprościej mówiąc, gdzie się znajduje w pamięci). Adres można uzyskać, umieszczając znak ampersand (&) przed nazwą zmiennej.

Jak używać wskaźników w C

Jeśli wydrukujesz adres zmiennej na ekranie, będzie on wyglądał jak liczba całkowicie losowa (co więcej, może się różnić w zależności od uruchomienia).

Spróbujmy tego w praktyce ze wskaźnikiem w przykładzie C

Jak używać wskaźników w C

Dane wyjściowe tego programu to -480613588.

A teraz, czym jest wskaźnik? Zamiast przechowywać wartość, wskaźnik będzie przechowywać adres zmiennej.


Zmienna wskaźnikowa

Int *y = &v;

ZMIENNA WSKAŹNIK
A wartość przechowywane w o imieniu adres przechowywania/pamięci A zmienna że wskazuje na adres przechowywania/pamięci inne zmienna

Deklarowanie wskaźnika

Podobnie jak zmienne, wskaźniki w Programowanie C muszą zostać zadeklarowane zanim będą mogły zostać użyte w programie. Wskaźniki mogą być nazwane w dowolny sposób, pod warunkiem, że przestrzegają reguł nazewnictwa języka C. Deklaracja wskaźnika ma następującą formę.

data_type * pointer_variable_name;

Tutaj,

  • typ danych jest podstawowym typem wskaźnika dla typów zmiennych języka C i wskazuje typ zmiennej, na którą wskazuje wskaźnik.
  • Gwiazdka (*: taka sama gwiazdka, jakiej używa się do mnożenia) jest operatorem pośrednim, deklarującym wskaźnik.

Zobaczmy kilka prawidłowych deklaracji wskaźników w tym samouczku dotyczącym wskaźników 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 */

Zainicjuj wskaźnik

Po zadeklarowaniu wskaźnika inicjujemy go jak standardowe zmienne z adresem zmiennej. Jeśli wskaźniki w programowaniu C nie są inicjowane i używane w programie, wyniki mogą być nieprzewidywalne i potencjalnie katastrofalne.

Aby uzyskać adres zmiennej, używamy operatora ampersand (&), umieszczonego przed nazwą zmiennej, której adres jest nam potrzebny. Inicjalizacja wskaźnika odbywa się za pomocą następującej składni.

Składnia wskaźnika

 pointer = &variable;

Poniżej znajduje się prosty program do ilustracji wskaźników:

#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;
}

Wyjście:

Address stored in a variable p is:60ff08
Value stored in a variable p is:10
OperaTor Znaczenie
* Służy 2 celom

  1. Deklaracja wskaźnika
  2. Zwraca wartość zmiennej, do której istnieje odwołanie
& Służy tylko 1 celowi

  • Zwraca adres zmiennej

Rodzaje wskaźników w C

Poniżej przedstawiono różne Rodzaje wskaźników w C:

Wskaźnik zerowy

Możemy utworzyć wskaźnik zerowy, przypisując wartość null podczas deklaracji wskaźnika. Ta metoda jest przydatna, gdy nie masz przypisanego żadnego adresu do wskaźnika. Wskaźnik zerowy zawsze zawiera wartość 0.

Poniższy program ilustruje użycie wskaźnika zerowego:

#include <stdio.h>
int main()
{
	int *p = NULL; 	//null pointer
	printf(“The value inside variable p is:\n%x”,p);
	return 0;
}

Wyjście:

The value inside variable p is:
0

Wskaźnik pustki

In Programowanie C, wskaźnik pustej przestrzeni nazywany jest także wskaźnikiem ogólnym. Nie ma żadnego standardowego typu danych. Wskaźnik void jest tworzony za pomocą słowa kluczowego void. Można go używać do przechowywania adresu dowolnej zmiennej.

Poniższy program ilustruje użycie wskaźnika typu void:

#include <stdio.h>
int main()
{
void *p = NULL; 	//void pointer
printf("The size of pointer is:%d\n",sizeof(p));
return 0;
}

Wyjście:

The size of pointer is:4

Dziki wskaźnik

Wskaźnik nazywany jest wskaźnikiem dzikim, jeśli nie jest inicjowany do niczego. Tego typu wskaźniki C nie są wydajne, ponieważ mogą wskazywać na nieznane miejsce w pamięci, co może powodować problemy w naszym programie i może prowadzić do awarii programu. Podczas pracy z dzikimi wskaźnikami należy zawsze zachować ostrożność.

Poniższy program ilustruje użycie wskaźnika dzikiego:

#include <stdio.h>
int main()
{
int *p; 	//wild pointer
printf("\n%d",*p);
return 0;
}

Wyjście:

timeout: the monitored command dumped core
sh: line 1: 95298 Segmentation fault      timeout 10s main

Inne typy wskaźników w „c” to:

  • Wiszący wskaźnik
  • Wskaźnik złożony
  • Blisko wskaźnika
  • Daleki wskaźnik
  • Ogromny wskaźnik

Bezpośrednie i pośrednie wskaźniki dostępu

W C istnieją dwa równoważne sposoby uzyskiwania dostępu do zmiennej treści i manipulowania nią

  • Dostęp bezpośredni: używamy bezpośrednio nazwy zmiennej
  • Dostęp pośredni: używamy wskaźnika do zmiennej

Rozumiemy to za pomocą poniższego programu

#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;}

Po skompilowaniu programu bez żadnych błędów wynik jest następujący:

Direct access, var = 1
Indirect access, var = 1

The address of var = 4202496
The address of var = 4202496

Indirect access, var = 48

Arytmetyka wskaźników w C

Operacje wskaźnika podsumowano na poniższym rysunku

Arytmetyka wskaźników w C
Wskaźnik Operanych

Operacja priorytetowa (pierwszeństwo)

Pracując ze wskaźnikami C, musimy przestrzegać następujących reguł priorytetów:

  • Operatory * i & mają taki sam priorytet jak operatory jednoargumentowe (negacja!, inkrementacja++, dekrementacja–).
  • W tym samym wyrażeniu operatory jednoargumentowe *, &,!, ++, – są oceniane od prawej do lewej.

Jeśli wskaźnik P wskazuje na zmienną X, wówczas * P można użyć wszędzie tam, gdzie można zapisać X.

Poniższe wyrażenia są równoważne:

int X =10
int *P = &Y;
For the above code, below expressions are true
Wyrażenie Wyrażenie równoważne
Y=*P+1

*P=*P+10

*P+=2

+***P

(*P)++

Y=X+1

X=X+10

X+=2

++X

X++

W drugim przypadku konieczne są nawiasy: ponieważ operatory jednoargumentowe * i ++ są obliczane od prawej do lewej, bez nawiasów zostałby zwiększony wskaźnik P, a nie obiekt, na który wskazuje P.

Poniższa tabela przedstawia arytmetykę i podstawowe operacje, które można stosować podczas pracy ze wskaźnikami języka C

Operacja Wyjaśnienie
Cesja int *P1,*P2
P1=P2;
P1 i P2 wskazują na tę samą zmienną całkowitą
Inkrementacja i dekrementacja Int *P1;
P1++;P1– ;
Dodawanie przesunięcia (stała) Dzięki temu wskaźnik może przesuwać N elementów w tabeli.
Wskaźnik zostanie zwiększony lub zmniejszony o N-krotność liczby bajtów typu zmiennej.
P1+5;

Wskaźniki i tablice C z przykładami

Tradycyjnie dostęp do elementów tablicy uzyskujemy za pomocą jej indeksu, ale tę metodę można wyeliminować za pomocą wskaźników. Wskaźniki ułatwiają dostęp do każdego elementu tablicy.

#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;
}

Wyjście:

1
2
3
4
5

Dodanie określonej liczby do wskaźnika spowoduje przesunięcie położenia wskaźnika do wartości uzyskanej przez operację dodawania. Załóżmy, że p jest wskaźnikiem, który obecnie wskazuje na położenie pamięci 0, jeśli wykonamy następującą operację dodawania, p+1, to zostanie ona wykonana w następujący sposób:

C Wskaźniki i tablice

Dodawanie/zwiększanie wskaźnika

Ponieważ p obecnie wskazuje lokalizację 0 po dodaniu 1, wartość wyniesie 1, a zatem wskaźnik będzie wskazywał lokalizację pamięci 1.

Wskaźniki i ciągi C z przykładami

Łańcuch to tablica obiektów typu char zakończona znakiem null „\ 0”. Za pomocą wskaźników możemy manipulować ciągami znaków. Ten wskaźnik w przykładzie C wyjaśnia tę sekcję

#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;
}

Wyjście:

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
!

Innym sposobem obsługi ciągów znaków jest użycie tablicy wskaźników, jak w poniższym programie:

#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;}

Wyjście:

Please remember these materials:
iron
copper
gold

Zalety wskaźników w C

  • Wskaźniki są przydatne przy uzyskiwaniu dostępu do komórek pamięci.
  • Wskaźniki zapewniają skuteczny sposób uzyskiwania dostępu do elementów struktury tablicowej.
  • Wskaźniki służą do dynamicznej alokacji i dealokacji pamięci.
  • Wskaźniki służą do tworzenia złożonych struktur danych, takich jak listy powiązane, grafy, drzewa itp.

Wady wskaźników w C

  • Wskaźniki są nieco skomplikowane do zrozumienia.
  • Wskaźniki mogą prowadzić do różnych błędów, takich jak błędy segmentacji, lub mogą uzyskać dostęp do komórki pamięci, która w ogóle nie jest potrzebna.
  • Jeśli do wskaźnika zostanie podana niepoprawna wartość, może to spowodować uszkodzenie pamięci.
  • Wskaźniki są również odpowiedzialne za wycieki pamięci.
  • Wskaźniki są stosunkowo wolniejsze niż zmienne.
  • Programistom bardzo trudno jest pracować ze wskaźnikami; dlatego też obowiązkiem programisty jest ostrożne manipulowanie wskaźnikiem.

Podsumowanie

  • Wskaźnik to nic innego jak miejsce w pamięci, w którym przechowywane są dane.
  • Wskaźnik służy do uzyskiwania dostępu do lokalizacji pamięci.
  • Istnieją różne typy wskaźników, takie jak wskaźnik zerowy, wskaźnik dziki, wskaźnik pusty i inne typy wskaźników.
  • Wskaźników można używać z tablicami i ciągami znaków, aby uzyskać bardziej efektywny dostęp do elementów.
  • Możemy tworzyć wskaźniki funkcji, aby dynamicznie wywoływać funkcję.
  • Na wskaźniku można wykonywać operacje arytmetyczne. Jest to tzw. arytmetyka wskaźnikowa.
  • Wskaźniki mogą również wskazywać na funkcję, co ułatwia wywoływanie różnych funkcji w przypadku definiowania tablicy wskaźników.
  • Jeśli chcesz obsługiwać inny zmienny typ danych, możesz użyć wskaźnika pustego rzutowania typu.