C'de İşaretçi nedir?
Pointer C, mağazalar başka değişkenin ele aldığı 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 bir sonraki / önceki hafıza konumuna 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
İnt türünde bir v değişkeni bildirirsek, v aslında bir değer depolar.
v şimdi sıfıra eşittir.
Bununla birlikte, her değişkenin değeri dışında bir adresi de vardır (veya basitçe belirtmek gerekirse, bellekte nerede olduğu). Adres, değişken adının önüne bir ve işareti (&) koyarak alınabilir.
Bir değişkenin adresini ekrana yazdırırsanız, tamamen rastgele bir sayı gibi görünecektir (dahası, çalıştırmadan çalışmaya farklı olabilir).
Bunu C örneğindeki işaretçi ile pratikte deneyelim
Bu programın çıktısı -480613588'dir.
Şimdi, işaretçi nedir? Bir değeri saklamak yerine, bir işaretçi bir değişkenin adresini y kaydeder.
İşaretçi Değişkeni
Int * y = & v;
DEĞİŞKEN |
IŞARETÇİ |
Adlandırılmış bir depolama / bellek adresinde saklanan bir değer |
Bir değişken olduğunu işaret depolama / bellek adresi bir değişken |
Bir İşaretçi Bildirme
Değişkenler gibi, C programlamadaki işaretçiler de programınızda kullanılmadan önce bildirilmelidir. İşaretçiler, C'nin adlandırma kurallarına uydukları sürece istediğiniz herhangi bir şekilde adlandırılabilir. Bir işaretçi bildirimi aşağıdaki biçime sahiptir.
data_type * pointer_variable_name;
Buraya,
- veri_türü , işaretçinin C değişken türlerinin temel türüdür ve işaretçinin işaret ettiği değişkenin türünü belirtir.
- Yönlendirme operatörü olan yıldız işareti (*: çarpma için kullanılan aynı yıldız) bir işaretçi bildirir.
Bu C işaretçisi 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ın
Bir gösterici tanımladıktan sonra, onu değişken adresli standart değişkenler gibi başlatıyoruz. C programlamadaki işaretçiler başlatılmamışsa ve programda kullanılmamışsa, sonuçlar tahmin edilemez ve potansiyel olarak felaket olabilir.
Bir değişkenin adresini almak için, adresine ihtiyacımız olan bir değişkenin adının önüne yerleştirilen ve işareti (&) operatörünü kullanırız. İşaretçi başlatma aşağıdaki sözdizimi ile yapılır.
İşaretçi Sözdizimi
pointer = &variable;
İşaretçi gösterimi için basit bir program aşağıda verilmiştir:
#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;}
Çıktı:
Address stored in a variable p is:60ff08Value stored in a variable p is:10
Şebeke | Anlam |
* | 2 amaca hizmet eder
|
& | Yalnızca 1 amaca hizmet eder
|
C İşaretçi Türleri
Aşağıda, C'deki farklı İşaretçi Türleri verilmiştir :
Boş işaretçisi
İşaretçi bildirimi sırasında boş değer atayarak boş bir işaretçi 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 boş göstericinin kullanımını göstermektedir:
#includeint main(){int *p = NULL; //null pointerprintf(“The value inside variable p is:\n%x”,p);return 0;}
Çıktı:
The value inside variable p is:0
Void Pointer
C programlamasında, bir boşluk gösterici aynı zamanda genel bir gösterici olarak da adlandırılır. Herhangi bir standart veri türü yoktur. Void anahtar sözcüğü kullanılarak bir boşluk gösterici oluşturulur. Herhangi bir değişkenin adresini saklamak için kullanılabilir.
Aşağıdaki program bir boşluk göstericisinin kullanımını göstermektedir:
#includeint main(){void *p = NULL; //void pointerprintf("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 şeyle başlatılmıyorsa, vahşi bir işaretçi olduğu söylenir. Bu tür C işaretçileri, programımızda sorunlara neden olabilecek ve programın çökmesine neden olabilecek bazı bilinmeyen bellek konumlarına işaret edebildikleri için verimli değildir. Vahşi işaretçilerle çalışırken her zaman dikkatli olunmalıdır.
Aşağıdaki program wild pointer kullanımını göstermektedir:
#includeint main(){int *p; //wild pointerprintf("\n%d",*p);return 0;}
Çıktı
timeout: the monitored command dumped coresh: 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
- İşaretçinin yakınında
- Uzak işaretçi
- Büyük işaretçi
Doğrudan ve Dolaylı Erişim İşaretçileri
C'de, değişken bir 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ıyoruz
- Dolaylı erişim: değişkene bir işaretçi kullanırız
Bunu aşağıdaki program yardımıyla anlayalım
#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;}
Programı hatasız derledikten sonra sonuç:
Direct access, var = 1Indirect access, var = 1The address of var = 4202496The address of var = 4202496Indirect access, var = 48
C İşaretçisi Aritmetiği
İşaretçi işlemleri aşağıdaki şekilde özetlenmiştir
Öncelikli işlem (ö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 (olumsuzluk !, artış ++, azaltma--).
- Aynı ifadede, tekli operatörler *, &,!, ++, - sağdan sola doğru değerlendirilir.
Bir P işaretçisi bir X değişkenini gösteriyorsa, X'in yazılabildiği her yerde * P kullanılabilir.
Aşağıdaki ifadeler eşdeğerdir:
int X = 10 int * P = & Y; Yukarıdaki kod için aşağıdaki ifadeler doğrudur | |
İfade | 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ğerlendirilirken, parantezler olmadan, P işaretçisi artırılır, P'nin işaret ettiği nesne değil.
Aşağıdaki tablo, C işaretçileriyle uğraşırken kullanılabilecek aritmetik ve temel işlemleri göstermektedir.
Operasyon | Açıklama |
Görev | int * P1, * P2 P1 = P2; P1 ve P2 aynı tam sayı değişkenine işaret eder |
Artış ve azalma | Int * P1; P1 ++; P1--; |
Bir ofset ekleme (Sabit) | Bu, işaretçinin bir tablodaki N öğeyi taşımasına izin verir. İş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çiler ve Diziler
Geleneksel olarak, dizi öğelerine dizinini kullanarak erişiriz, ancak bu yöntem işaretçiler kullanılarak ortadan kaldırılabilir. İşaretçiler, her dizi öğesine erişimi kolaylaştırır.
#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;}
Çıktı
12345
Bir işaretçiye belirli bir sayı eklemek, işaretçi konumunu bir toplama işlemi ile elde edilen değere taşıyacaktır. P'nin şu anda hafıza konumunu 0 gösteren bir gösterici olduğunu varsayalım, eğer aşağıdaki toplama işlemini gerçekleştirirsek, p + 1 o zaman bu şekilde çalışacaktır:
P şu anda 1 ekledikten sonra 0 konumuna işaret ettiğinden, değer 1 olacak ve dolayısıyla işaretçi bellek konumu 1'i gösterecektir.
Örneklerle C İşaretçiler ve Dizeler
Bir dizge, null karakteri '\ 0' ile biten bir char nesneleri dizisidir. İşaretçileri kullanarak dizeleri değiştirebiliriz. C örneğindeki bu işaretçi bu bölümü açıklamaktadır
#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 Çıktı
First character is:HNext character is:ePrinting all the characters in a stringHelloGuru99!Dizeleri işlemenin başka bir yolu, aşağıdaki programdaki gibi bir dizi işaretçi kullanmaktır:
#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;} Çıktı:
Please remember these materials:ironcoppergoldC'deki İşaretçilerin Avantajları
- İşaretçiler, bellek konumlarına erişmek için kullanışlıdır.
- İşaretçiler, bir dizi yapısının öğelerine erişim için verimli bir yol sağlar.
- İşaretçiler, dinamik bellek ayırmanın yanı sıra serbest bırakma için kullanılır.
- İşaretçiler, bağlantılı liste, grafik, ağaç vb. Gibi karmaşık veri yapılarını oluşturmak için kullanılır.
C'deki İşaretçilerin Dezavantajları
- İşaretçilerin anlaşılması biraz karmaşıktır.
- İşaretçiler, bölümleme hataları gibi çeşitli hatalara yol açabilir veya hiç gerekli olmayan bir bellek konumuna erişebilir.
- İşaretçiye yanlış bir değer sağlanırsa, bellek 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 kullanmak programcının sorumluluğundadır.
Özet
- Bir işaretçi, verilerin depolandığı bir hafıza 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, boşluk işaretçisi ve diğer işaretçi türleri gibi çeşitli işaretçiler vardır.
- İşaretçiler, öğelere daha verimli bir şekilde erişmek için dizi ve dizeyle birlikte kullanılabilir.
- Bir işlevi dinamik olarak çağırmak için işlev işaretçileri oluşturabiliriz.
- Aritmetik işlemler, işaretçi aritmetiği olarak bilinen bir işaretçi üzerinde yapılabilir.
- İşaretçiler, bir dizi işaretçi tanımlama durumunda farklı işlevleri çağırmayı kolaylaştıran işlevi de gösterebilir.
- Farklı değişken veri türlerini ele almak istediğinizde, typecast void işaretçisi kullanabilirsiniz.