logo

C Çift İşaretçi (İşaretçiden İşaretçiye)

Bildiğimiz gibi, C'de bir değişkenin adresini saklamak için bir işaretçi kullanılır. İşaretçi, bir değişkenin erişim süresini azaltır. Ancak C'de başka bir işaretçinin adresini saklamak için bir işaretçi de tanımlayabiliriz. Böyle bir işaretçi, çift işaretçi (işaretçiden işaretçiye) olarak bilinir. İlk işaretçi bir değişkenin adresini saklamak için kullanılırken, ikinci işaretçi birinci işaretçinin adresini saklamak için kullanılır. Bunu aşağıda verilen diyagramdan anlayalım.

c'deki işaretçiden işaretçiye

Double pointer bildirmenin sözdizimi aşağıda verilmiştir.

 int **p; // pointer to a pointer which is pointing to an integer. 

Aşağıdaki örneği düşünün.

 #include void main () { int a = 10; int *p; int **pp; p = &a; // pointer p is pointing to the address of a pp = &p; // pointer pp is a double pointer pointing to the address of pointer p printf('address of a: %x
',p); // Address of a will be printed printf('address of p: %x
',pp); // Address of p will be printed printf('value stored at p: %d
',*p); // value stoted at the address contained by p i.e. 10 will be printed printf('value stored at pp: %d
',**pp); // value stored at the address contained by the pointer stoyred at pp } 

Çıktı

 address of a: d26a8734 address of p: d26a8738 value stored at p: 10 value stored at pp: 10 

C çift işaretçi örneği

Bir işaretçinin başka bir işaretçinin adresini işaret ettiği bir örnek görelim.

ağ topolojileri
C işaretçisinden işaretçi örneğine

Yukarıdaki şekilde görüldüğü gibi p2, p (fff2) adresini, p ise sayı değişkeninin (fff4) adresini içermektedir.

 #include int main(){ int number=50; int *p;//pointer to int int **p2;//pointer to pointer p=&number;//stores the address of number variable p2=&p; printf('Address of number variable is %x 
',&number); printf('Address of p variable is %x 
',p); printf('Value of *p variable is %d 
',*p); printf('Address of p2 variable is %x 
',p2); printf('Value of **p2 variable is %d 
',*p); return 0; } 

Çıktı

 Address of number variable is fff4 Address of p variable is fff4 Value of *p variable is 50 Address of p2 variable is fff2 Value of **p variable is 50 

S. Aşağıdaki programın çıktısı ne olacaktır?

 #include void main () { int a[10] = {100, 206, 300, 409, 509, 601}; //Line 1 int *p[] = {a, a+1, a+2, a+3, a+4, a+5}; //Line 2 int **pp = p; //Line 3 pp++; // Line 4 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 5 *pp++; // Line 6 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 7 ++*pp; // Line 8 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 9 ++**pp; // Line 10 printf('%d %d %d
',pp-p,*pp - a,**pp); // Line 11 } 

Açıklama

Çift işaretçi sorusu

Yukarıdaki soruda pointer aritmetiği double pointer ile kullanılmıştır. Bir p işaretçisi dizisi ile işaret edilen 6 öğeden oluşan bir dizi tanımlanır. İşaretçi dizisi p, çift işaretçi pp ile işaret edilmiştir. Bununla birlikte, yukarıdaki görüntü size belleğin a dizisine ve p işaretçi dizisine nasıl tahsis edildiği hakkında kısa bir fikir verir. p'nin elemanları, a dizisinin her elemanına işaret eden işaretçilerdir. Dizi adının dizinin temel adresini içerdiğini bildiğimizden, bir işaretçi olarak çalışacaktır ve *(a), *(a+1), vb. kullanılarak değerde gezinilebilir mi? Resimde gösterildiği gibi , a[0]'a aşağıdaki yollardan erişilebilir.

java ile karşılaştırıldığında tamsayı
  • a[0]: dizinin ilk elemanına erişmenin en basit yoludur
  • *(a): dizinin ilk elemanının adresini sakladığından, onun değerine onun üzerindeki dolaylı işaretçiyi kullanarak erişebiliriz.
  • *p[0]: Eğer a[0]'a p işaretçisi kullanılarak erişilecekse, o zaman p işaretçi dizisinin ilk elemanında dolaylılık operatörünü (*) kullanabiliriz, yani *p[0].
  • **(pp): pp işaretçi dizisinin temel adresini sakladığından, *pp işaretçi dizisinin ilk öğesinin değerini, yani tamsayı dizisinin ilk öğesinin adresini verecektir. **p, tamsayı dizisinin ilk öğesinin gerçek değerini verecektir.

Programa gelince, Satır 1 ve 2, tamsayı ve işaretçi dizisini göreceli olarak bildirir. Satır 3, çift işaretçiyi p işaretçi dizisine başlatır. Şekilde görüldüğü gibi dizinin adresi 200'den başlıyorsa ve tamsayı boyutu 2 ise işaretçi dizisi 200, 202, 204, 206, 208, 210 değerlerini içerecektir. işaretçi dizisinin temel adresi 300'dür; çift ​​işaretçi pp işaretçi dizisinin adresini, yani 300'ü içerir. 4 numaralı satır, pp'nin değerini 1 artırır, yani pp artık 302 adresini gösterecektir.

5 numaralı satır üç değeri yazdıran bir ifade içerir, yani pp - p, *pp - a, **pp. Her birini hesaplayalım.

  • pp = 302, p = 300 => pp-p = (302-300)/2 => pp-p = 1 yani 1 basılacaktır.
  • pp = 302, *pp = 202, a = 200 => *pp - a = 202 - 200 = 2/2 = 1 yani 1 basılacaktır.
  • pp = 302, *pp = 202, *(*pp) = 206 yani 206 yazdırılacaktır.

Dolayısıyla 5. satır sonucunda konsola 1, 1, 206 çıktısı yazdırılacaktır. 6.satırda *pp++ yazıyor. Burada iki tekli operatörün * ve ++ aynı önceliğe sahip olacağını fark etmeliyiz. Dolayısıyla çağrışım kuralı gereği sağdan sola doğru değerlendirilecektir. Bu nedenle *pp++ ifadesi (*(pp++)) olarak yeniden yazılabilir. Çünkü pp = 302, şimdi 304 olacaktır. *pp 204'ü verecektir.

java ters dize

7. satırda yine üç değeri yazdıran ifade yazılır, yani pp-p, *pp-a, *pp. Her birini hesaplayalım.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2 yani 2 basılacaktır.
  • pp = 304, *pp = 204, a = 200 => *pp-a = (204 - 200)/2 = 2 yani 2 basılacaktır.
  • pp = 304, *pp = 204, *(*pp) = 300 yani 300 basılacaktır.

Dolayısıyla 7. satır sonucunda konsola 2, 2, 300 çıktısı yazdırılacaktır. 8. satıra +*pp yazılır. İlişkisellik kuralına göre bu, (++(*(pp))) olarak yeniden yazılabilir. pp = 304, *pp = 204 olduğundan, *pp = *(p[2]) = 206 değeri artık a[3]'e işaret edecektir.

9. satırda yine üç değeri yazdıran ifade yazılır, yani pp-p, *pp-a, *pp. Her birini hesaplayalım.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2 yani 2 basılacaktır.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3 yani 3 basılacaktır.
  • pp = 304, *pp = 206, *(*pp) = 409 yani 409 yazdırılacaktır.

Dolayısıyla 9. satır sonucunda konsola 2, 3, 409 çıktısı yazdırılacaktır. 10. satıra ++**pp yazılır. çağrışım kuralına göre bu, (++(*(*(pp)))) olarak yeniden yazılabilir. pp = 304, *pp = 206, **pp = 409, ++**pp => *pp = *pp + 1 = 410. Başka bir deyişle, a[3] = 410.

python programlama örnekleri

11. satırda yine üç değeri yazdıran ifade yazılır, yani pp-p, *pp-a, *pp. Her birini hesaplayalım.

  • pp = 304, p = 300 => pp - p = (304 - 300)/2 => pp-p = 2 yani 2 basılacaktır.
  • pp = 304, *pp = 206, a = 200 => *pp-a = (206 - 200)/2 = 3 yani 3 basılacaktır.
  • 8. satırda **s. = 410.

Dolayısıyla 9. satırın sonucunda konsola 2, 3, 410 çıktısı yazdırılacaktır.

Sonunda programın tamamının çıktısı şu şekilde verilecektir:

Çıktı

 1 1 206 2 2 300 2 3 409 2 3 410