C'de İşaretçiler: C Programlamada İşaretçi Nedir? Türler

C'de İşaretçi Nedir?

The Işaretçi C'de, başka bir değişkenin adresini saklayan bir değişkendir. Bir işaretçi, başka bir işaretçi işlevine başvurmak için de kullanılabilir. Bir işaretçi artırılabilir/azaltılabilir, yani sonraki/önceki hafıza konumunu işaret etmek için. İşaretçinin amacı bellek alanından tasarruf etmek ve daha hızlı yürütme süresi elde etmektir.

C'de İşaretçiler Nasıl Kullanılır

Eğer int türünde bir v değişkeni bildirirsek, v aslında bir değer depolayacaktır.

C'de İşaretçiler Nasıl Kullanılır

v şimdi sıfıra eşit.

Bununla birlikte, her değişkenin değerin yanı sıra kendi adresi de vardır (veya daha basit bir ifadeyle, bellekte bulunduğu yere). Adres, değişken adının önüne ve işareti (&) konularak alınabilir.

C'de İşaretçiler Nasıl Kullanılır

Bir değişkenin adresini ekrana yazdırırsanız, tamamen rastgele bir sayı gibi görünecektir (üstelik, çalıştırmadan çalıştırmaya farklılık gösterebilir).

Bunu C örneğinde pointer ile pratikte deneyelim.

C'de İşaretçiler Nasıl Kullanılır

Bu programın çıktısı -480613588'dir.

Şimdi işaretçi nedir? Bir işaretçi, bir değeri saklamak yerine bir değişkenin adresini saklar.


İşaretçi Değişkeni

Dahili *y = &v;

DEĞİŞKEN İŞARET
A değer içinde depolanmış adlı depolama/bellek adresi A değişken o işaret depolama/bellek adresi bir diğeri değişken

Bir İşaretçi Bildirmek

Değişkenler gibi işaretçiler de C programlama programınızda kullanılmadan önce bildirilmeleri gerekir. İşaretçiler, C'nin adlandırma kurallarına uydukları sürece istediğiniz şekilde adlandırılabilir. Bir işaretçi bildirimi aşağıdaki biçime sahiptir.

data_type * pointer_variable_name;

Burada,

  • veri tipi C'nin değişken türlerinin işaretçinin temel türüdür ve işaretçinin işaret ettiği değişkenin türünü belirtir.
  • Dolaylı bir işleç olan yıldız işareti (*: çarpma işleminde kullanılan yıldız işaretinin aynısı) bir işaretçiyi tanımlar.

Bu C işaretçileri eğitiminde bazı geçerli işaretçi bildirimlerini görelim:

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 */

Bir işaretçiyi başlat

Bir işaretçi bildirdikten sonra, onu değişken adresli standart değişkenler gibi başlatırız. C programlamasındaki işaretçiler başlatılmazsa ve bir programda kullanılırsa, sonuçlar tahmin edilemez ve potansiyel olarak feci olabilir.

Bir değişkenin adresini almak için, adresine ihtiyacımız olan değişkenin adından önce yerleştirilen ve işareti (&) operatörünü kullanırız. İşaretçi başlatma aşağıdaki sözdizimiyle yapılır.

İşaretçi Söz Dizimi

 pointer = &variable;

İşaretçi gösterimi için basit bir program aşağıda verilmiştir:

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

Çıktı:

Address stored in a variable p is:60ff08
Value stored in a variable p is:10
Kullanım anlam
* 2 amaca hizmet eder

  1. Bir işaretçinin beyanı
  2. Başvurulan değişkenin değerini döndürür
& Yalnızca 1 amaca hizmet eder

  • Bir değişkenin adresini döndürür

C'de İşaretçi Türleri

Aşağıda farklı olanlar yer almaktadır C'de İşaretçi Türleri:

Boş işaretçisi

Pointer bildirimi sırasında null değer atayarak null pointer oluşturabiliriz. Bu yöntem, işaretçiye atanmış herhangi bir adresiniz olmadığında kullanışlıdır. Boş gösterici her zaman 0 değerini içerir.

Aşağıdaki program, null işaretçisinin kullanımını göstermektedir:

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

Çıktı:

The value inside variable p is:
0

Geçersiz İşaretçi

In C programlamavoid işaretçisine genel işaretçi de denir. Herhangi bir standart veri tipi yoktur. Bir void işaretçisi void anahtar sözcüğü kullanılarak oluşturulur. Herhangi bir değişkenin adresini saklamak için kullanılabilir.

Aşağıdaki program, boş bir işaretçinin kullanımını göstermektedir:

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

Çıktı:

The size of pointer is:4

Vahşi işaretçi

Bir işaretçinin, herhangi bir şeye başlatılmıyorsa, vahşi bir işaretçi olduğu söylenir. Bu tür C işaretçileri verimli değildir çünkü programımızda sorunlara neden olabilecek bazı bilinmeyen bellek konumlarına işaret edebilir ve programın çökmesine neden olabilir. Vahşi işaretçilerle çalışırken her zaman dikkatli olunmalıdır.

Aşağıdaki program vahşi işaretçinin kullanımını göstermektedir:

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

Çıktı:

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

'C'deki diğer işaretçi türleri aşağıdaki gibidir:

  • Sarkan işaretçi
  • Karmaşık işaretçi
  • Yakın işaretçi
  • Uzak işaretçi
  • Büyük işaretçi

Doğrudan ve Dolaylı Erişim İşaretçileri

C'de değişken içeriğe erişmenin ve bunları değiştirmenin iki eşdeğer yolu vardır.

  • Doğrudan erişim: doğrudan değişken adını kullanırız
  • Dolaylı erişim: değişkene bir işaretçi kullanırız

Bunu aşağıdaki program yardımıyla anlayalım.

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

Programı hatasız derledikten sonra sonuç:

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

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

Indirect access, var = 48

C'de İşaretçi Aritmetiği

İşaretçi işlemleri aşağıdaki şekilde özetlenmiştir

C'de İşaretçi Aritmetiği
Işaretçi Operaleri

Öncelikli çalışma (öncelik)

C işaretçileriyle çalışırken aşağıdaki öncelik kurallarına uymalıyız:

  • * ve & operatörleri, tekli operatörlerle aynı önceliğe sahiptir (olumsuzlama!, artırma++, azaltma–).
  • Aynı ifadede *, &,!, ++, – tekli operatörleri sağdan sola doğru değerlendirilir.

Bir P işaretçisi bir X değişkenine işaret ediyorsa, X'in yazılabildiği her yerde * P kullanılabilir.

Aşağıdaki ifadeler eşdeğerdir:

int X =10
int *P = &Y;
For the above code, below expressions are true
ifade Eşdeğer İfade
Y=*P+1

*P=*P+10

*P+=2

+****P

(*P)++

Y=X+1

X=X+10

X+=2

++X

X ++

İkinci durumda, parantezlere ihtiyaç vardır: tekli operatörler * ve ++ sağdan sola doğru değerlendirildiğinden, parantezler olmadan P'nin işaret ettiği nesne değil, P işaretçisi artırılır.

Aşağıdaki tablo, C işaretçileriyle uğraşırken kullanılabilecek aritmetik ve temel işlemleri göstermektedir.

Çalışma açıklama
Atama int *P1,*P2
P1=P2;
P1 ve P2 aynı tamsayı değişkenine işaret eder
Arttırma ve azaltma Dahili *P1;
P1++;P1– ;
Ofset ekleme (Sabit) Bu, işaretçinin bir tablodaki N öğeyi taşımasına olanak tanır.
İşaretçi, değişken türünün bayt (lar) sayısının N katı kadar artırılacak veya azaltılacaktır.
P1+5;

Örneklerle C İşaretçileri ve Dizileri

Geleneksel olarak dizi elemanlarına indeksini kullanarak erişiriz, ancak bu yöntem işaretçiler kullanılarak ortadan kaldırılabilir. İşaretçiler her dizi öğesine erişmeyi kolaylaştırır.

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

Çıktı:

1
2
3
4
5

Bir işaretçiye belirli bir sayı eklemek, işaretçi konumunu bir toplama işlemiyle elde edilen değere taşıyacaktır. p'nin şu anda bellek konumu 0'ı işaret eden bir işaretçi olduğunu varsayalım, aşağıdaki toplama işlemini gerçekleştirirsek, p+1, bu şekilde yürütülecektir:

C İşaretçileri ve Dizileri

İşaretçi Ekleme/Arttırma

p şu anda 0 eklendikten sonra 1 konumunu gösterdiğinden, değer 1 olacak ve dolayısıyla işaretçi 1 bellek konumunu gösterecektir.

Örneklerle C İşaretçileri ve Dizeleri

Bir dize, '\ 0' boş karakteriyle biten bir karakter nesneleri dizisidir. İşaretçileri kullanarak dizeleri işleyebiliriz. C örneğindeki bu işaretçi bu bölümü açıklamaktadır

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

Çıktı:

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
!

Dizeleri işlemenin bir başka yolu da aşağıdaki programdaki gibi bir dizi işaretçi kullanmaktır:

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

Çıktı:

Please remember these materials:
iron
copper
gold

C'de İşaretçilerin Avantajları

  • İşaretçiler bellek konumlarına erişim için kullanışlıdır.
  • İşaretçiler bir dizi yapısının öğelerine erişmenin etkili bir yolunu sağlar.
  • İşaretçiler, dinamik bellek ayırmanın yanı sıra serbest bırakma için de kullanılır.
  • İşaretçiler, bağlantılı liste, grafik, ağaç vb. gibi karmaşık veri yapıları oluşturmak için kullanılır.

C'de İşaretçilerin Dezavantajları

  • İşaretçileri anlamak biraz karmaşıktır.
  • İşaretçiler, bölümlendirme hataları gibi çeşitli hatalara yol açabilir veya hiç gerekli olmayan bir bellek konumuna erişebilir.
  • Bir işaretçiye yanlış bir değer sağlanırsa hafıza bozulmasına neden olabilir.
  • İşaretçiler ayrıca bellek sızıntısından da sorumludur.
  • İşaretçiler değişkenlerinkinden nispeten daha yavaştır.
  • Programcılar işaretçilerle çalışmayı çok zor buluyor; bu nedenle bir işaretçiyi dikkatli bir şekilde değiştirmek programcının sorumluluğundadır.

ÖZET

  • İşaretçi, verilerin depolandığı bir bellek konumundan başka bir şey değildir.
  • Bellek konumuna erişmek için bir işaretçi kullanılır.
  • Boş işaretçi, vahşi işaretçi, geçersiz işaretçi ve diğer işaretçi türleri gibi çeşitli işaretçi türleri vardır.
  • Öğelere daha verimli erişmek için işaretçiler dizi ve dizeyle birlikte kullanılabilir.
  • Bir işlevi dinamik olarak çağırmak için işlev işaretçileri oluşturabiliriz.
  • İşaretçi aritmetiği olarak bilinen bir işaretçi üzerinde aritmetik işlemler yapılabilir.
  • İşaretçiler ayrıca bir dizi işaretçinin tanımlanması durumunda farklı işlevlerin çağrılmasını kolaylaştıran işlevlere de işaret edebilir.
  • Farklı değişken veri türleriyle ilgilenmek istediğinizde typecast void işaretçisini kullanabilirsiniz.