Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

C#’ta Gösterici(Pointer) – Gösterici Bildirimi ve Gösterici Operatörleri – III

Merhaba,

Önceki yazılarımdan olan C#’ta Gösterici(Pointer) Nedir? – I ve C#’ta Gösterici(Pointer) – unsafe Komutu – II başlıklı makalelerimde sırasıyla C# programlama dilinde göstericilere dair unsafe komutuna kadar temellendirmede bulunmuştuk. Şimdi ise gösterici bildirimi ve gösterici operatörleri üzerine bir içerik oluşturacağız.

Öncelikle C# programlama dilinde göstericilere dair teorik bilgimize katkıda bulunarak sarmal bir şekilde ilerleyelim.

İlk olarak bilmenizi istediğim, gösterici dediğimiz yapı normal değişkenler gibi tanımlansada C#’ta ayrı bir veri türüdürler. Yani demek istediğim o ki; “int” tipinden değişkenler sayısal değerleri, “char” tipinden değişkenler karakterleri yahut “bool” tipinden değişkenlerin ise mantıksal değerleri tutması nasıl onları değer tipli değişken yapıyorsa, gösterici türleride nesnelerin bellekteki adreslerini tuttukları için kendi başlarına ayrı bir veri türünü nitelendirmektedirler.

Her ne kadar göstericiler ayrı veri türü olsalarda birazdan göreceğimiz üzere tüm değer tipleri ile tanımlanabilmektedirler.(sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool vs.) Bunun yanında struct(yapılar)’da değer tipinden olduklarından dolayı haliyle struct üzerinde de göstericileri kullanabilir, tanımlayabiliriz.

Değer türlerinin dışında enumeration-enum yapıları ile birlikte “void” keywordü ilede göstericiler tanımlanabilmektedirler. Eğer işaretçiyi özel bir veri türüne tanımlamak istemiyorsak “void” anahtar sözcüğü kullanılmaktadır. Böylece ilgili işaretçi herhangi bir veri türünden değer için adres tutabilir.

class yapılarına gelirsek eğer referans tipinden olduklarından dolayı zaten nesnelerin referansları bellekteki adresleri refere ettiğinden/işaretlediğinden/kullandığından dolayı gösterici kullanımına izin verilmemektedir.

Son olarak göstericiler “object” sınıfından türemedikleri için gösterici türleri ile object arasında tür dönüşümü yapılamaz. Ayrıca boxing ve unboxing işlemlerini de desteklemez.

Bu kadar teorik bilgiden sonra artık göstericinin nasıl tanımlandığına daha doğrusu bildirildiğine göz atalım.

Gösterici Bildirimi(*)

C#’ta, C ve C++ dillerinde olduğu gibi gösterici tanımlayabilmek için göstericinin türünün yanına *(asterisk/yıldız) karakteri eklenmelidir.

    class MyClass
    {
        enum MyEnum { }
        struct MyStruct { }
        public MyClass()
        {
            unsafe
            {
                int* x;
                bool* y;
                char* z;
                MyStruct* w;
                MyEnum* q;
                void* t;
            }
        }
    }

Yukarıdaki kod bloğunu incelerseniz eğer “int”, “bool” ve “char” değer tiplerinden göstericiler tanımlanmıştır. Ayriyetten “MyStruct” isminde oluşturulan struct tipinden ve “MyEnum” isminde oluşturulan enum tipinden birer göstericide tanımlanmıştır. Sonuncu göstericimiz ise “void” tipinde bir türe bağlı olmaksızın tanımlanmıştır. Dikkat ederseniz tanımlamalarda tiplerin yanındaki * ifadesini kaldırırsak bunlar normal değişken olacaktır. * ifadesi sayesinde değişken değil gösterici(pointer) olmaktadırlar.

* karakteri tipin yanında belirtiliyorsa o tanımlamanın bir gösterici olduğunu belirtir.

Eğer ki birden fazla gösterici aynı türden olacaksa aşağıdaki gibi tanımlama yapabiliriz.

            unsafe
            {
                int* x, y, z;
            }

C# dilinde göstericiler tamamen ayrı bir veri türü olarak ele alındığı için yukarıdaki deyim ile aslında aşağıdaki gibi üç farklı gösterici bildirmiş bulunmaktayız.

            unsafe
            {
                int* x;
                int* y;
                int* z;
            }

Bir göstericinin işaret edeceği bellek adresini sabit bir şekilde verebiliriz. Örneğin; bellekteki “231242” adresini herhangi bir gösterici ile işaret ettirmek istiyorsak aşağıdaki gibi çalışabiliriz.

            unsafe
            {
                decimal* i = (decimal*)231242;
            }

Bu tarz bir bildirim çok ama çok tehlikelidir. Çünkü sabit olarak belirtilen adreste ne olduğunu bilmiyoruz. Düşünsenize… Elimizdeki içeriği ne olduğu belli olmayan bu adres içerisinde işletim sisteminin kullandığı bellek bölgesi olabilir yahut bilgisayarın o anki korumalı ya da sıfır korumalı bilgileri barındıran hassas bir bellek noktası olabilir. O yüzden sabit olarak belirtilen bellek adreslerini kurcalamaktan mümkün mertebe çekinmenizi tavsiye ederim.

Şimdi ise bildiklerimizden yola çıkarak bir genellemeye varmak için aşağıdaki kod bloğunu inceleyiniz.

            unsafe
            {
                int* i;
            }

Bu tanımlama neyi gösteriyordu? “int” tipinden bir pointerı. Yani “int” tipinden değişkenleri gösterecek/işaretleyecek bir pointerı.

Peki tamam…

            unsafe
            {
                int** i;
            }

O halde bu tanımlama neyi gösteriyor? “int” tipinden bir göstericiyi işaretleyen bir pointerı. Yani anlayacağınız göstericiler, göstericileri işaretleyebiliyor. Burada bir sonraki konuya ithafen dikkat etmenizi istediğim husus, bu şekilde göstericilerin birbirlerini işaretlediği durumlarda bu göstericilerin işaretledikleri bellek adreslerindeki nihai değeri elde etmek için birazdaha kompleks bir kullanımda bulunacağız. Tabi yeri ve zamanı gelince bu noktayı size hatırlatacağım…

Bu konuya değin akılda kalması maksatlı şu örneğide incelemekte fayda var.

            unsafe
            {
                int*** i;
            }

“int” tipinden bir göstericiyi(int***) işaret eden bir başka göstericiyi(int***) işaret eden pointer(int***) tanımlanmıştır.

Son olarakta bir işaretçi dizisi nasıl tanımlanır sorusunun cevabını verip konumuzu burada noktalayalım.

            unsafe
            {
                int*[] dizi;
            }

Evet… Bu şekilde de bir işaretçi dizisi tanımlanabilmektedir.

Görüldüğü üzere gösterici bildirimini tam teferruatıyla ele almış bulunmaktayız.

Sevgili okurlarım…
Makalemizin kâh başlığında kâh ilk girişinde belirttiğimiz gibi gösterici bildirimi ve gösterici operatörlerinden bahsedeceğimizi belirtmiştim. Ama görüyorsunuz ki gösterici bildirimlerini noktaladığımız anda makalemiz oldukça şişmiş bulunmaktadır. O yüzden gösterici operatörlerini sonraki makalemizde ele alma kararını vermiş bulunmaktayım.

O halde bir sonraki devam niteliğindeki makalemizde görüşmek üzere diyorum…
Hoşçakalın…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

2 Cevaplar

  1. 06 Mayıs 2017

    […] önceki içeriğimizde C#’ta Gösterici(Pointer) – Gösterici Bildirimi ve Gösterici Operatörleri – III başlığı altında göstericilerde, gösterici bildirimi üzerine giriş ve detay niteliğinde […]

  2. 09 Ocak 2019

    […] C#’ta Gösterici(Pointer) – Gösterici Bildirimi ve Gösterici Operatörleri – III […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir