Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Sefer Algan
Sefer Algan
http://www.seferalgan.com
İletişme geçmek için tıklayın.
71 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler:  C# / VC#/.NET Sefer Algan
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Başlangıç
Kategori : C# / VC#/.NET
Yayınlanma Tarihi : 1.3.2003
Okunma Sayısı : 56083
Yorum Sayısı : 3     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 18.4.2024
Turhal Temizer
Mac OS/X Removing CUDA 18.4.2024
Burak Selim Şenyurt
Kurumsal Yazılımcının Oyun Geliştirme ile İmtihanı 18.4.2024
Burak Selim Şenyurt
Matematik ve Oyun Programlama - Missile Command - Final 18.4.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
C#'ta Gösterici(Pointer) Kullanmak - I
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon

Göstericiler(Pointer) alt seviye programlama için olmazsa olmaz yapılardır. Göstericiler nesnelerin bellekte tutuldukları adresleri saklayan veri yapılarıdır. Bu makalede C#'ta kullanımı çok fazla gerekli olmayan göstericilerin nasıl kulanıldıklarını inceleyeceğiz. Bu yazı göstericiler hakkında temel bilgilere sahip olduğunuzu varsaymaktadır.

.NET' in altyapısında gösterici kavramı sıklıkla kullanılırken göstericilerin açıkca kullanımı programcılar için gizlenmitir. Bunun nedeni gösterici kullanımının programlardaki görülemeyen hatalara sıkça yol açabilmesidir. Özellikle dili yeni öğrenenler için gösterici hataları içinden çıkılmaz bir hale gelebilmektedir. C#'ta göstericiler yerine referans değişkenleri mevcuttur. Referanslar heap bellek bölgesindeki nesnelerin başlangıç adresini tutar. Ancak bu adresin değerine kesinlikle ulaşamayız. Oysa C ve C++ dillerinde stack bölgesindeki değişkenlerin de adreslerine erişbilmemiz mümkündür. Üstelik değişkenlerin adreslerini örneğin 0x965474 şeklinde elde etmemiz bile mümkündür. C ve C++ programcılarına pek yabancı gelmeyecektir bunlar, ancak programlama dünyasına C# ile giren biri için göstericilere neden ihtiyaç duyabileceğimiz pek anlamlı gelmeyebilir. Şunu da söyeleyelim ki çok istisnai durumlar dışında göstericilere ihtiyacımız olmayacak, peki bu istisna durumlar nelerdir?

  • Geriye Uyumluluk(Backward Compatibility) : COM ve WinAPI'deki fonksiyonlar gibi sık sık gösterici kullanan fonksiyonları C# ile programlarımızdan çağırabilmek için parametre olarak gösterici alan fonksiyonlara gösterici göndermemiz gerekebilir. Eğer C# ta gösterici kullanımına izin verilmemiş olsaydı tür uyumsuzluğu yüzünden gösterici kullanan eski COM ve DLL'lere erişebilmemiz mümkün olamazdı.

  • Performans : C ve C++ dillerinin günümüze kadar çok popüler olmasının altında yatan nedenlerden biri de belleğe direkt erişimi sağladığı içinperformansın inanılmaz derecede yükselmesidir. Bizim için performansın çok önemli olduğu yerlerde gösterici kullanmamızdan daha doğal birşey olamaz.

  • Alt Seviye İşlemler : Donanım arayüzleri ile direkt bir ilişki içerisinde olacak programlarda göstericilerin kullanımı mecburi gibidir. Bazen de belleğe kullanıcıların direkt erişebilmesi gereken programlar olabilir. Bu durumlarda da göstericilerden faydalanabiliriz.
Bütün bunların yanında gösterici kullanmanın bir çok sıkıntıyıda beraberinde getireceği kesindir. Öncelikle kullanımının zor olması ve kestirilmesi zor olan hatalara yol açabilmesi bu sıkıntıların en başında gelenidir. Zaten C#'ta gösterici kullanacağımız zaman kodu unsafe(güvensiz) anahtar sözcüğü ile işaretlememiz gerekir. Aksi halde program derlenemeyecektir. Normal bir metot içinde gösterici kullanımı yasaklanmıştır.

Şimdi de unsafe anahtar sözcüğünün kullanımına örnekler verelim.

1-) unsafe olarak işaretlenen sınıfların bütün metotlarında gösterici kullanabiliriz.


unsafe class Sınıf
{

}


2-) Normal bir metot içinde herhangi bir bloğu unsafe olarak aşağıdaki gibi işaretleyip dilediğimiz gibi gösterici kullanabiliriz. unsafe bloklarının dışında ise gösterici kullanamayız.

int NormalMetot(int a, string str)
{
    unsafe
    {

    }
}


3-) Normal bir metodu unsafe olarak işaretleyip sadece o metodun içinde de gösterici kullanabiliriz.

unsafe int NormalMetot(int a, string str)
{

}


4-) Bir sınıfın üye değişkenlerinden biri unsafe olarak işaretlenip gösterici olarak bildirilebilir. Ancak bir metot içerisinde yerel bir gösterici tanımlanamaz. Yerel bir gösterici tanımlamak için unsafe olarak işaretlenmiş metod yada blok kullanılır.

class Sınıf
{
     unsafe char *ptr;
}


Gösterici Tanımlama ve Gösterici Operatörleri

Göstericiler aşağıdaki gibi tanımlanabilir.

char* ptr1, ptr2;
int* ptr3;


ptr1 ve ptr2 char türden bir gösterici iken ptr3 int türden bir göstericdir. Bir göstericide iki bileşen vardır. Bu bileşenlerden birincisi adres bileşenidir. Adres bileşeni nesnenin bellekte bulunduğu başlangıç adresidir. İkinci bileşen ise tür bileşenidir. Bu bileşen ise ilgili adresteki nesneye ulaşmak istediğimizde bellekten ne kadarlık bilgili okunacağını sağlar. Örneğin int türden bir adresteki bilgiyi okumak istediğimizde 4 byte'lık bir bilgi okunacaktır, aynı şekilde char türden bir gösterici ise 2 byte'lık bir bilgi okunacaktır.

& operatörü

Adres operatörü olarak bilinen bu operatör değişkenlerin veya nesnelerin bellekte bulundukları adresleri elde etmek için kullanılır. Bu operatör hangi tür değişkenle kullunılırsa o türden bir gösterici üretilir.

* operatörü

İçerik operatörü olan *, bir adresteki bilgileri elde etmek için kullanılır. Aşağıdaki programda bu iki operatörün kullanımına bir örnek verilmiştir.

using System;

class Class1
{
     unsafe static void Main()
     {
          int* ptr1;
          char* ptr2;

          int a = 50;
          ptr1 = &a;
          int Adres = (int)ptr1;
          Console.WriteLine("{0:X}",Adres);

          char ch = 'A';
          ptr2 = &ch;
          *ptr2 = 'B';
          Console.WriteLine(ch);
     }
}


Bu programı derleyebilmek için komut satırı derleyicisene programın içinde unsafe bloğunun olduğunu belirtmemiz gerekir. Bunun için komut satırına

csc /unsafe KaynakKod.cs

yada

csc -unsafe KaynakKod.cs

yazarak programı derleyebilirsiniz. Eğer Visual Studio.NET kullanıyorsanız projeye sağ tıklayıp proje özelliklerine gelip Build kısmından "Allow unsafe code blocks" kısmını true olacak şekilde değiştirin.

Programı çalıştırdığınızda ekrana a değişkeninin adresi ve B karekteri yazılacaktır. Adres bilgisini ekrana yazdırmadan önce göstericide tutulan adresi normal bir türe nasıl dönüştürdüğümüze dikkat edin. Bunu yapmamızın sebebi Consol.WriteLine() metodunun gösterici parametres alan versiyonunun olmamasıdır.

C#'ta tür güvenliğinin ne kadar önemli olduğunu vurgulamak için aşağıdaki deyimleri örnek verebiliriz.

int* ptr1;
*ptr1 = 50;

Bu deyimleri içeren bir program derlenemeyecektir. Çünkü ptr1 göstericisinde hangi adresin tutulduğu belli değildir. Bu yüzden adresi belli olmayan bellek bölgesine bir değer yerleştirmek imkansızdır. C ve C++ dillerinde bu kullanım tamamen geçerlidir. Ama gelin bir de bunun sakıncasına bir göz atalım. ptr1 göstericisi tanımlandığında ptr1 de rastgele bir adres değeri bulunmaktadır. Bu adreste rastgele bir adres olduğu için o an bellekte çalışan kendi programımızdaki bir değişkenin adresi bile olabilir. Yada sistemde çalışan başka bir prosesteki elemanların adresleri olabilir. Kaynağını bilmediğimiz bir adresteki değeri * operatörü ile değiştirdiğimizde hiç tahmin edemeyeceğimiz çalışma zamanı hataları alabiliriz. İşin kötüsü adresler rastgele olduğu için programımızın test aşamasında bu hatalar oluşmayabilir. Adresler nasıl rastgele ise hataların oluşması da rastgeledir. Programımız piyasada iken böyle bir hatanın farkına varılması iş maliyetlerini ne kadar artırdığını siz tahmin edin artık. Bütün bu dezavantajlar göstericilerin asla gereksiz olduğu anlamına gelmemelidir. Sadece göstericileri kullanırken daha dikkatli davranmamız gerektiğinin göstergesidir.

Göstericiler arasında tür dönüşümleri mümkündür. Örneğin int türden bir gösterici char türden bir göstericiye aşağıdaki gibi dönüştürülebilir.

char* ptr1
int* ptr2;

ptr1 = (char*)ptr2


Aynı şekilde bir gösterici de tamsayı türlerine dönüştürülebilir. Adresler tam sayı türünden birer sayı oldukları için bunu yapabilmemiz son derece normal bir durumdur. Bir önceki çalışan programda da Console.WriteLine() metodu ile ekrana yazmak istediğimiz nesnenin adresini tamsayı türlerinden birini çevirdiğimizi hatırlayın. Örneğin aşağıdaki deyimleri içeren bir program derlenemeyecektir.

char* ptr1
char ch = 'A';
ptr1 = ch;

Console.WriteLine(ptr1)


Göstericilerle ilgili diğer önemli yapı ise void göstericilerdir. void olan göstericilerde tür bilgisi saklanmamaktadır. void göstericilere herhangi bir türden gösterici atanabilir. void göstericiler daha çok eskiden yazılmış API fonksiyonlarında void parametre alan fonksiyoları programlarımız içerisinden çağırmak için kullanılır. void göstericilerin kullanımına aşağıda bir örnek verilmiştir.


int* ptr1;
void * x;
x = ptr1;


sizeof operatörü

sizeof operatörü temel türlerin ve yapıların bellekte ne kadar alan kapladıklarını verir. Örneğin sizeof(int) = 4, sizeof(char) = 2 ' dir. sizeof operatörünü sınıflar için kullanamayız ancak tanımlayacağımız yapılar için kullanabiliriz. 

Bu yazının sonuna geldik. Bir sonraki yazımızda yapı göstericileri tanımlamayı sınıflar ile göstericiler arasındaki ilişkiyi, gösterici aritmetiğini inceleyip örnek bir gösterici uygulaması yapacağız.


Kaynaklar:

C# and The .NET Platform (Andrew Troelsen)
Professional C# 2nd Edition (Wrox)
MSDN Kütüphanesi
Makale:
C#'ta Gösterici(Pointer) Kullanmak - I C#, Visual C# ve .NET Sefer Algan
  • Yazılan Yorumlar
  • Yorum Yaz
KAS
13
2009
c++ da yazılmış bir DLL i c#.NET kullanmaya çalışıyordum..Makalenizi okuduktan sonra soru işaretleri biraz daha azaldı sanıyorum..iyi çalışmlar..
NİS
3
2003
teşekkürler.
MAR
1
2003
güzel bir yazı olmuş başarılarınızın devamını dilerim
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor