C Dilinde İşaretçiler (Pointer in C Language), Pointer Aritmetiği, Pointer’ların Pointer’ları

Yiğit Küçükkıratlı
birtakimmuhendislikler
4 min readJun 5, 2023
Photo by Ilya Pavlov on Unsplash

Selam, bugün sizlerle C dilinin en kafa karıştırıcı temellerinden biri olan pointer kavramını inceleyeceğiz. Hiç vakit kaybetmeden başlayalım.

POINTER NEDİR?

C dilinde pointer, bellekteki bir değişkenin adresini tutan bir veri türüdür. Bir bellek adresi, o adreste saklanan veriye erişmek için kullanılır. Pointerlar, C dilinin güçlü bir özelliği olarak kabul edilir ve doğru kullanıldığında programlamanın verimliliğini artırır.

Bir pointer, bir veri türüne sahip olan bir bellek adresini işaret eder. Pointer değişkenleri, “*” operatörü ile tanımlanır. Örneğin, aşağıdaki gibi bir pointer tanımı yapılabilir:

int *ptr;

Bu, “ptr” adında bir integer tipinde pointer tanımladığımızı belirtir. Pointer değişkenlerinin değeri, bellekteki bir adres olabilir. Bellek adresine erişmek için “&” operatörü kullanılır. Örneğin, aşağıdaki gibi bir değeri bir pointer değişkene atayabiliriz:

int num = 10;
int *ptr = #

Bu, “ptr” adındaki pointer değişkeninin “num” değişkeninin bellekteki adresini tuttuğunu gösterir.

Karıştırma!!: Pointerlar, bellekteki verilere erişmek için dereferans (indirection) operatörü olan “*” operatörü kullanılarak kullanılır. Bu, pointer’ı tanımlamak için gereken asteriksten farklı bir anlam taşır. Aşağıdaki örnekte, pointer aracılığıyla bellekteki veriye erişiyoruz:

int num = 10;
int *ptr = #
printf("num degeri: %d\n", num);
printf("ptr degeri: %d\n", *ptr);

Bu kod, “num” değişkeninin değerini doğrudan yazdırmak yerine, “ptr” pointerının işaret ettiği bellek adresindeki değeri yazdırır. Dereferans operatörü, pointerın işaret ettiği bellek adresindeki değeri elde etmek için kullanılır.

Pointerlar, fonksiyonlara parametre geçmek, dinamik bellek yönetimi, veri yapıları ve daha birçok durumda kullanılabilir. Bellekteki adreslere erişerek verilerin doğrudan manipüle edilmesine olanak tanırlar. Ancak pointerların doğru kullanılması önemlidir, aksi takdirde hatalara neden olabilir ve bu da programın güvenliğini tehlikeye atacaktır.

POINTERLARIN BELLEK TABLOSU İLE GÖSTERİMİ

Bir örnek üzerinden ilerleyelim.

int a = 15;
int *ptr = &a;

Bu durumda belleğimizin şu şekilde olmasını bekleriz:

Bellek verileri örnek olarak verilmiştir.

Gördüğünüz gibi ptr pointer’ımızın değeri a’nın belleği olmuştur.

DİZİLERDE POINTER ve POINTER ARİTMETİĞİ

Dizilerde, bir dizinin ilk elemanının bellek adresini tutan bir pointer kullanılır. Dizi adı, aynı zamanda bellekte dizinin başlangıç adresini temsil eder. Bu nedenle, bir dizi adı bir pointer olarak kullanılabilir ve dizinin ilk elemanına işaret eder.

Bir dizi tanımlandığında, bellekte ardışık bellek hücreleri ayrılır ve her bir hücre dizi elemanlarını saklar. Dizi adı, bu bellek bloğunun başlangıç adresini temsil eder. Örneğin, aşağıdaki gibi bir dizi tanımlayalım:

int numbers[5] = {1, 2, 3, 4, 5};

Bu dizi, 5 elemanlı bir integer dizisidir. Dizi adı numbers, dizinin ilk elemanının bellek adresini temsil eder. Bu nedenle, numbers dizi adını bir pointer olarak kullanabilir ve dizinin ilk elemanına işaret eder.

int *ptr = numbers;

Bu kodda, numbers dizisinin başlangıç adresini ptr adlı bir pointer değişkene atadık. ptr şimdi numbers dizisinin ilk elemanına işaret ediyor.

Pointer aritmetiği kullanarak dizinin diğer elemanlarına erişebiliriz. Örneğin, ptr pointerını birer birer artırarak dizideki diğer elemanlara ulaşabiliriz.

printf("%d\n", *ptr); // İlk elemanı yazdırır: 1

ptr++; // Pointer'ı bir sonraki elemana ilerlet

printf("%d\n", *ptr); // İkinci elemanı yazdırır: 2

printf("%d\n", *(ptr+1)) // Üçüncü elemanı yazdırır: 3

Pointer kullanarak dizinin elemanlarına erişmek, döngülerde veya fonksiyonlarda dizi üzerinde işlem yapmak için sıkça kullanılan bir tekniktir. Pointerlar, bellek adresleri üzerinde doğrudan manipülasyon yapmayı sağlar ve dizilerle çalışmayı daha verimli hale getirebilir.

Şimdi tablo üzerinden bir örnekle ilerleyelim.

int dizi[] = {8,7,6,10};
int *ptr = dizi;
//int *ptr = &dizi[0]; de diyebilirdik.

Gördüğünüz gibi dizi bellekte sıralı bir şekilde dizildi ve eğer dizinin elemanlarına erişmek istersek direkt ptr pointerımızı kullanabiliriz.

printf("%d\n",*ptr); // 8
printf("%d\n",*(ptr+1)); // 7
printf("%d\n",*(ptr+2)); // 6
printf("%d\n",*ptr+3); // 11 BURAYA DİKKAT!! 8 + 3 = 11

POINTERLARIN POINTERLARI

Pointerların pointerları, bir pointerın adresini tutan ve dolaylı olarak bellekteki başka bir bellek adresini işaret eden pointerlardır. Pointerların pointerları, “çift düzeyli” (double indirection) veya “çoklu düzeyli” (multilevel indirection) olarak da adlandırılır.

Bir pointerın pointerını tanımlamak için, pointer türünün yıldız (*) işaretini bir kez daha kullanırız. Örneğin, aşağıdaki gibi bir tanım yapabiliriz:

int num = 10;
int *ptr = #
int **ptr_to_ptr = &ptr;

Bu örnekte, ptr_to_ptr adında bir pointerın pointerını tanımladık. ptr_to_ptr, ptr pointerının adresini tutar ve dolaylı olarak num değişkenine erişim sağlar. Yani ptr_to_ptr ile num değişkenine ulaşabiliriz.

Çift düzeyli pointerlar genellikle çoklu düzeyli veri yapılarında ve dinamik bellek yönetiminde kullanılır. Örneğin, çoklu düzeyli bir diziyi temsil etmek için pointerların pointerları kullanılabilir. Ayrıca, işaretçilerin dinamik olarak oluşturulduğu veya değiştirildiği durumlarda da pointerların pointerları kullanılabilir.

Pointerların pointerları, bazı durumlarda daha karmaşık bir yapıya sahip olabilir. Örneğin, bir fonksiyonun dönüş değeri olarak bir pointerın pointerı döndürülebilir veya bir fonksiyonun parametresi olarak bir pointerın pointerı alınabilir. Bu şekilde, bellekteki verilere dolaylı olarak erişmek ve manipüle etmek için çoklu düzeyli işaretçi yapıları kullanılabilir. Bir örnekle pekiştirelim:

int dizi[] = {3,1,5,10};
int *ptr = dizi;
int **pptr = &ptr;

Bu şekilde bir kod bloğu yazarsak bellekte aşağıdaki gibi görünecektir.

Bu elemanlara ulaşmak için,

printf("%d\n",**pptr); // 3
printf("%d\n",*(*pptr+1)); // 1
printf("%d\n",*(*pptr+2)); // 5
printf("%d\n",*(*pptr+3)); // 10

şeklinde bir kullanım söz konusu olabilir..

Pointerlara temel bir giriş yaptık. Diğer yazılarıma aşağıdan ulaşabilirsiniz. Hepinize kolay gelsin.

--

--