C++

C++ İşaretçileri nasıl kullanılır?

C++ İşaretçileri nasıl kullanılır?
Bir bilgisayarın hafızası uzun bir hücre dizisidir. Her hücrenin boyutuna bayt denir. Bir bayt, alfabenin İngilizce karakteri tarafından işgal edilen bir alandır. Sıradan anlamda bir nesne, bellekte ardışık bir bayt kümesidir. Her hücrenin bir tamsayı olan ve genellikle onaltılık biçimde yazılmış bir adresi vardır. Bellekteki bir nesneye erişmenin üç yolu vardır. İşaretçi olarak bilinen bir şey kullanılarak bir nesneye erişilebilir. Referans olarak bilinenler kullanılarak erişilebilir. Yine de bir tanımlayıcı kullanılarak erişilebilir. Bu makalenin odak noktası, işaretçilerin ve referansların kullanımıdır. C++'da sivri uçlu nesne ve işaretçi nesnesi vardır. Sivri nesnenin ilgi nesnesi var. İşaretçi nesnesi, sivri uçlu nesnenin adresine sahiptir.

Tanımlayıcıları, işlevleri ve dizileri dahil olmak üzere C++ hakkında temel bilgilere sahip olmanız gerekir; Bu makaleyi anlamak için.

İşaretçi nesnesi ve sivri nesne, her birinin tanımlayıcısı vardır.

Operatörün Adresi &

Bu tekli bir operatördür. Bir tanımlayıcı tarafından takip edildiğinde, tanımlayıcının nesnesinin adresini döndürür. Aşağıdaki beyanı göz önünde bulundurun:

int ptdInt;

Aşağıdaki kod, aşağıdaki ifade, ptdInt tarafından tanımlanan adresi döndürür:

&ptdInt

Kod yazarken tam adresi (numarayı) bilmenize gerek yoktur.

Dolaylı Operatör, *

Bu, işaretçiler bağlamında tekli bir operatördür. Genellikle bir tanımlayıcının önüne yazılır. Tanımlayıcının bir bildiriminde kullanılıyorsa, tanımlayıcı yalnızca sivri uçlu nesnenin adresini tutan işaretçi nesnesidir. Bir şeyi döndürmek için işaretçi nesne tanımlayıcısının önünde kullanılırsa, döndürülen şey sivri nesnenin değeridir.

İşaretçi Oluşturma

Aşağıdaki kod segmentine bir göz atın:

float ptdFloat;
yüzer *ptrFloat;
ptrFoat = &ptdFloat;

Segment, sivri uçlu nesnenin bildirilmesiyle başlar, ptdFloat. ptdFloat, yalnızca bir kayan nesneyi tanımlayan bir tanımlayıcıdır. Ona gerçek bir nesne (değer) atanmış olabilir, ancak bu durumda ona hiçbir şey atanmamıştır. Segmentin sonraki kısmında, işaretçi nesnesinin bildirimi var. Bu tanımlayıcının önündeki dolaylı operatör, sivri bir nesnenin adresini tutması gerektiği anlamına gelir. İfadenin başındaki kayan nesne türü, sivri nesnenin bir kayan nokta olduğu anlamına gelir. İşaretçi nesnesi, her zaman sivri uçlu nesneyle aynı tiptedir. ptrFoat, yalnızca bir işaretçi nesnesini tanımlayan bir tanımlayıcıdır.

Kodun son ifadesinde, işaretli nesnenin adresi işaretçi nesnesine atanır. Operatörün adresinin kullanımına dikkat edin, &.

Yukarıdaki son ifade (satır), işaretçi nesnesini başlatma olmadan bildirdikten sonra, başlatmanız gerektiğinde dolaylı operatöre ihtiyacınız olmadığını gösterir. Aslında üçüncü (son) satırda yönlendirme operatörünü kullanmak bir sözdizimi hatasıdır.

İşaretçi nesnesi, aşağıdaki gibi tek bir ifadede işaretli nesne tarafından bildirilebilir ve başlatılabilir:

float ptdFloat;
kayan nokta *ptrFoat = &ptdFloat;

Önceki kod bölümünün ilk satırı ve bu, aynı. Önceki kod bölümünün ikinci ve üçüncü satırları burada tek bir ifadede birleştirildi.

Yukarıdaki kodda, işaretçi nesnesini bildirirken ve başlatırken, yönlendirme operatörünün kullanılması gerektiğini unutmayın. Ancak, başlatma daha sonra yapılacaksa kullanılmaz. İşaretçi nesnesi, sivri nesnenin adresiyle başlatılır.

Aşağıdaki kod segmentinde, sivri uçlu nesnenin içeriğini döndürmek için dolaylı operatör kullanılır.

int ptdInt = 5;
int *ptrInt = &ptdInt;
cout << *ptrInt << '\n';

çıktı 5.

Buradaki son ifadede, yönlendirme operatörü, işaretçi tanımlayıcısı tarafından işaret edilen değeri döndürmek için kullanılmıştır. Bu nedenle, bir bildirimde kullanıldığında, yönlendirme operatörünün tanımlayıcısı, işaret edilen nesnenin adresini tutacaktır. Bir dönüş ifadesinde kullanıldığında, işaretçi tanımlayıcısıyla birlikte, dolaylı operatör, sivri uçlu nesnenin değerini döndürür.

Bir İşaretçiye Sıfır Atama

İşaretçi nesnesi her zaman sivri uçlu nesnenin türüne sahip olmalıdır. İşaretçi nesnesini bildirirken, sivri uçlu nesnenin veri türü kullanılmalıdır. Ancak, ondalık sıfır değeri, aşağıdaki kod segmentinde olduğu gibi işaretçiye atanabilir:

int ptdInt = 5;
int *ptrInt;
ptrInt = 0;
veya segmentte,
int ptdInt = 5;
int *ptrInt = 0;

Her iki durumda da işaretçiye (tanımlayıcı) boş işaretçi denir; anlamı, hiçbir yere işaret etmiyor. Yani, sivri uçlu herhangi bir nesnenin adresine sahip değildir. Burada 0, ondalık sıfırdır ve onaltılık sıfır değildir. Onaltılık sıfır, bilgisayar belleğinin ilk adresini gösterir.

Boş gösterici ile gösterilen değeri elde etmeye çalışmayın. Bunu denerseniz, program derlenebilir, ancak çalışmayabilir.

Sabit İşaretçi Olarak Dizi Adı

Aşağıdaki diziyi göz önünde bulundurun:

int dizi[] = 000, 100, 200, 300, 400;

Dizinin adı, arr aslında dizinin ilk öğesinin adresini içeren tanımlayıcıdır. Aşağıdaki ifade dizideki ilk değeri döndürür:

*varış

Artırma operatörü ++ dizisi ile farklı davranır. 1 eklemek yerine, işaretçinin adresini dizideki sonraki öğenin adresiyle değiştirir. Ancak dizinin adı sabit bir işaretçidir; yani içeriği (adresi) değiştirilemez veya artırılamaz. Bu nedenle, artırmak için dizinin başlangıç ​​adresinin sabit olmayan bir işaretçiye aşağıdaki gibi atanması gerekir:

int *ptr = dizi;

Şimdi, ptr dizinin sonraki elemanına işaret edecek şekilde artırılabilir. ptr burada bir işaretçi nesnesi olarak bildirildi. Burada * olmadan, bir işaretçi olmaz; bir int nesnesini tutmak ve bir bellek adresini tutmamak için bir tanımlayıcı olacaktır.

Aşağıdaki kod parçası nihayet dördüncü öğeye işaret ediyor:

++ptr;
++ptr;
++ptr;

Aşağıdaki kod dizinin dördüncü değerini verir:

int dizi[] = 000, 100, 200, 300, 400;
int *ptr = dizi;
++ptr;
++ptr;
++ptr;
cout << *ptr << '\n';

çıktı 300.

Tanımlayıcı Olarak İşlev Adı

Bir işlevin adı, işlevin tanımlayıcısıdır. Aşağıdaki işlev tanımını göz önünde bulundurun:

int fn()

cout << "seen" << '\n';
dönüş 4;

fn, işlevin tanımlayıcısıdır. İfade,

&fn

hafızadaki fonksiyonun adresini döndürür. fn sivri uçlu nesne gibidir. Aşağıdaki bildirim, bir işleve bir işaretçi bildirir:

int (*işlev)();

Sivri uçlu nesnenin tanımlayıcısı ve işaretçi nesnesinin tanımlayıcısı farklıdır. func, bir işleve yönelik bir işaretçidir. fn bir fonksiyonun tanımlayıcısıdır. Ve böylece, func aşağıdaki gibi fn'ye işaret edebilir:

işlev = &fn;

func'nin değeri (içeriği), fn'nin adresidir. İki tanımlayıcı, aşağıdaki gibi bir başlatma ifadesi ile bağlantılı olabilirdi:

int (*işlev)() = &fn;

İşlev işaretçilerini ve skaler işaretçileri işlemedeki farklılıkları ve benzerlikleri not edin. func, bir işleve yönelik bir işaretçidir; sivri nesnedir; skaler bir işaretçiden farklı olarak bildirilir.

fonksiyon ile çağrılabilir,

fn()
veya
işlev()

*func() ile çağrılamaz.

İşlevin parametreleri olduğunda, ikinci parantezler parametre türlerini içerir ve parametreler için tanımlayıcılara sahip olmaları gerekmez. Aşağıdaki program bunu göstermektedir:

#Dahil etmek
ad alanı std kullanarak;
float fn(float fl, int in)

dönüş fl;

int ana()

kayan nokta (*işlev)(kayan nokta, int) = &fn;
kayan nokta değeri = işlev(2.5, 6);
cout << val << '\n';
0 döndür;

çıktı 2.5.

C++ Referansı

C++'da referans vermek, bir tanımlayıcı için eşanlamlı (başka bir isim) üretmenin bir yoludur. & operatörünü kullanır, ancak işaretçiler için & ile aynı şekilde kullanılmaz. Aşağıdaki kod segmentini göz önünde bulundurun:

int myInt = 8;
int &yourInt = myInt;
cout << myInt << '\n';
cout << yourInt << '\n';

Çıktı:

8
8

İlk ifade, myInt tanımlayıcısını başlatır; ben.e. myInt bildirildi ve değeri tutmak için yapıldı, 8. İkinci ifade yeni bir tanımlayıcı yapar, yourInt myInt ile eşanlamlıdır. Bunu başarmak için & operatörü, bildirimdeki veri türü ile yeni tanımlayıcı arasına yerleştirilir. cout ifadeleri, iki tanımlayıcının eşanlamlı olduğunu gösterir. Bu durumda değeri döndürmek için önüne * koymanız gerekmez . Sadece tanımlayıcıyı kullanın.

myInt ve yourInt burada, iki farklı nesne değil. Bunlar, 8 değerine sahip bellekte aynı konumu referans alan (tanımlayan) iki farklı tanımlayıcıdır. myInt'in değeri değiştirilirse, yourInt'in değeri de otomatik olarak değişecektir. yourInt'in değeri değiştirilirse, myInt'in değeri de otomatik olarak değişecektir.

Referanslar aynı türdendir.

Bir Fonksiyona Referans

Bir skalere referansınız olabileceği gibi, bir fonksiyona referansınız da olabilir. Ancak, bir fonksiyona referans kodlamak, bir skalere referansı kodlamaktan farklıdır. Aşağıdaki program bunu göstermektedir:

#Dahil etmek
ad alanı std kullanarak;
float fn(float fl, int in)

dönüş fl;

int ana()

float (&func)(float, int) = fn;
kayan nokta değeri = işlev(2.5, 6);
cout << val << '\n';
0 döndür;

çıktı 2.5.

func'ı fn ile eşanlamlı yapan ana işlevdeki ilk ifadeye dikkat edin. Her ikisi de aynı işleve başvurur. & öğesinin tek kullanımına ve konumuna dikkat edin. Yani & burada referans operatörüdür ve operatörün adresi değil. İşlevi çağırmak için iki adı da kullanın.

Referans tanımlayıcı, işaretçi tanımlayıcı ile aynı değildir.

İşaretçi döndüren işlev

Aşağıdaki programda işlev, sivri uçlu nesnenin adresi olan bir işaretçi döndürür:

#Dahil etmek
ad alanı std kullanarak;
float *fn(float fl, int in)

kayan nokta *fll = &fl;
geri dönüş;

int ana()

kayan nokta *val = fn(2.5, 6);
cout << *val << '\n';
0 döndür;

çıktı 2.5

İşlevdeki ilk ifade olan fn(), yalnızca bir işaretçi nesnesi oluşturmak için oradadır. İşlev imzasındaki * öğesinin tek kullanımına ve konumuna dikkat edin. Ayrıca, işaretçinin (adres), main() işlevinde başka bir işaretçi nesnesi tarafından nasıl alındığını da not edin.

Referans döndüren işlev

Aşağıdaki programda, işlev bir başvuru döndürür:

#Dahil etmek
ad alanı std kullanarak;
float &fn(float fl, int in)

kayan nokta &frr = fl;
dönüş frr;

int ana()

kayan nokta &değer = fn(2.5, 6);
cout << val << '\n';
0 döndür;

çıktı 2.5.

Fonksiyondaki ilk ifade olan fn() sadece bir referans oluşturmak için oradadır. İşlev imzasındaki & öğesinin tek kullanımını ve konumunu not edin. Ayrıca referansın başka bir referans tarafından main() işlevinde nasıl alındığını da not edin.

Bir Fonksiyona İşaretçi Geçirmek

Aşağıdaki programda, aslında kayan noktalı bir nesnenin adresi olan bir işaretçi, işleve argüman olarak gönderilir:

#Dahil etmek
ad alanı std kullanarak;
float fn(float *fl, int in)

dönüş *fl;

int ana()

kayan nokta v = 2.5;
kayan nokta değeri = fn(&v, 6);
cout << val << '\n';
0 döndür;

çıktı 2.5

İşlev imzasındaki şamandıra parametresi için * kullanımına ve konumuna dikkat edin. fn() işlevinin değerlendirilmesi başlar başlamaz aşağıdaki ifade yapılır:

kayan nokta *fl = &v;

Hem fl hem de &v, 2'yi tutan aynı sivri uçlu nesneye işaret ediyor.5. *fl dönüş ifadesinde bir bildirim değildir; işaretçi nesnesi tarafından işaret edilen sivri uçlu nesnenin değeri anlamına gelir.

Bir Fonksiyona Referans Geçmek

Aşağıdaki programda, fonksiyona argüman olarak bir referans gönderilir:

#Dahil etmek
ad alanı std kullanarak;
float fn(float &fl, int in)

dönüş fl;

int ana()

kayan nokta v = 2.5;
kayan nokta değeri = fn(v, 6);
cout << val << '\n';
0 döndür;

çıktı 2.5

İşlev imzasındaki şamandıra parametresi için & öğesinin kullanımına ve konumuna dikkat edin. fn() işlevinin değerlendirilmesi başlar başlamaz aşağıdaki ifade yapılır:

kayan nokta &fl = v;

Bir Fonksiyona Dizi Geçirmek

Aşağıdaki program, bir diziyi bir işleve nasıl geçireceğinizi gösterir:

#Dahil etmek
ad alanı std kullanarak;
int fn(int dizi[])

dönüş dizisi[2];

int ana()

int dizi[] = 000, 100, 200, 300, 400;
int değer = fn(dizi);
cout << val << '\n';
0 döndür;

çıktı 200.

Bu programda, geçirilen dizidir. İşlev imzasının parametresinin boş bir dizi bildirimi olduğunu unutmayın. İşlev çağrısındaki argüman, yalnızca oluşturulan bir dizinin adıdır.

Bir C++ İşlevi bir Dizi döndürebilir mi??

C++'daki bir işlev, bir dizinin değerini döndürebilir, ancak diziyi döndüremez. Aşağıdaki programın derlenmesi bir hata mesajıyla sonuçlanır:

#Dahil etmek
ad alanı std kullanarak;
int fn(int dizi[])

dönüş dizisi;

int ana()

int dizi[] = 000, 100, 200, 300, 400;
int değer = fn(dizi);
0 döndür;

Bir İşaretçinin İşaretçisi

Bir işaretçi başka bir işaretçiye işaret edebilir. Yani, bir işaretçi nesnesi, başka bir işaretçi nesnesinin adresine sahip olabilir. Hala hepsi aynı tipte olmalı. Aşağıdaki kod segmenti bunu göstermektedir:

int ptdInt = 5;
int *ptrInt = &ptdInt;
int **ptrptrInt = &ptrInt;
cout << **ptrptrInt << '\n';

çıktı 5.

İşaretçiden işarete bildirimde, double * kullanılır. Son sivri uçlu nesnenin değerini döndürmek için double * hala kullanılıyor.

İşaretçi Dizisi

Aşağıdaki program, bir dizi işaretçinin nasıl kodlanacağını gösterir:

#Dahil etmek
ad alanı std kullanarak;
int ana()

int num0=000, num1=100, num2=200, num3=300, num4=400;
int *no0=&num0, *no1=&num1, *no2=&num2, *no3=&num3, *no4=&num4;
int *dizi[] = no0, no1, no2, no3, no4;
cout << *arr[4] << '\n';
0 döndür;

Çıktı:

400

Dizinin bildiriminde * öğesinin kullanımına ve konumuna dikkat edin. Dizide bir değer döndürürken * kullanımına dikkat edin. İşaretçi işaretçileri ile iki * dahil edilir. İşaretçi dizisi durumunda, dizi tanımlayıcısı bir işaretçi olduğundan bir * zaten halledilmiştir.

Değişken Uzunluk Dizeleri Dizisi

Bir dize değişmezi, bir işaretçi döndüren bir sabittir. Değişken uzunluklu dizeler dizisi, bir işaretçiler dizisidir. Dizideki her değer bir işaretçidir. İşaretçiler, bellek konumlarının adresleridir ve aynı boyuttadır. Farklı uzunluktaki dizeler dizide değil, bellekte başka bir yerdedir. Aşağıdaki program kullanımı göstermektedir:

#Dahil etmek
ad alanı std kullanarak;
int ana()

const char *dizi[] = "kadın", "erkek", "kız", "yetişkin";
cout << arr[2] << '\n';
0 döndür;

Çıktı "kız".

Dizinin bildirimi, sabit için ayrılmış "const" kelimesiyle başlar; ardından karakter için "char", ardından yıldız işareti, her öğenin bir işaretçi olduğunu belirtmek için *. Diziden bir dize döndürmek için, her dizenin işaretçisinin örtük doğası nedeniyle * kullanılmaz. * kullanılırsa, dizenin ilk öğesi döndürülür.

İşaretçi döndüren bir İşleve İşaretçi

Aşağıdaki program, bir işaretçi döndüren bir işleve işaretçinin nasıl kodlandığını gösterir:

#Dahil etmek
ad alanı std kullanarak;
int *fn()

int sayı = 4;
int *ara = #
dönüş arası;

int ana()

int *(*işlev)() = &fn;
int değer = *işlev();
cout << val << '\n';
0 döndür;

çıktı 4.

Bir işaretçinin bir işaretçi döndüren bir işleve bildirilmesi, bir işaretçinin sıradan bir işleve bildirilmesine benzer, ancak öncesinde bir yıldız işareti bulunur. main() işlevindeki ilk ifade bunu gösterir. İşaretçiyi kullanarak işlevi çağırmak için önüne * ile gelin.

Sonuç

Bir skalere işaretçi oluşturmak için şunun gibi bir şey yapın:,

şamandıra sivri;
kayan nokta *işaretçi = &pointed;

* iki anlamı vardır: bir bildirimde, bir işaretçiyi belirtir; bir şey döndürmek için, sivri nesnenin değeri içindir.

Dizi adı, dizinin ilk öğesinin sabit bir göstergesidir.

Bir işleve işaretçi oluşturmak için şunları yapabilirsiniz:,

int (*işlev)() = &fn;

burada fn() başka bir yerde tanımlanmış bir fonksiyondur ve func işaretçidir.

&'nin iki anlamı vardır: bir bildirimde, başka bir tanımlayıcıyla aynı nesneye bir referansı (eş anlamlısını) belirtir; bir şeyi iade ederken, adresi anlamına gelir.

Bir fonksiyona referans oluşturmak için şunları yapabilirsiniz:,

float (&refFunc)(float, int) = fn;

burada fn() başka bir yerde tanımlanmış bir fonksiyondur ve refFunc referanstır.

Bir işlev bir işaretçi döndürdüğünde, döndürülen değer bir işaretçi tarafından alınmalıdır. Bir fonksiyon bir referans döndürdüğünde, döndürülen değer bir referans tarafından alınmalıdır.

Bir işleve bir işaretçi iletildiğinde, parametre bir bildirimdir, argüman ise sivri uçlu bir nesnenin adresidir. Bir işleve başvuru iletirken, parametre bir bildirimdir, argüman ise başvurudur.

Bir işleve bir dizi aktarırken, parametre bir bildirimdir, argüman ise [] olmadan dizi adıdır. C++ işlevi bir dizi döndürmez.

Bir işaretçiden işaretçiye, uygun olduğunda bir yerine iki * gerekir.

Chrys

Linux için En İyi Oyun Konsolu Emülatörleri
Bu makale, Linux için kullanılabilen popüler oyun konsolu öykünme yazılımını listeleyecektir. Öykünme, oyun konsollarının, komut setlerinin ve ilgili ...
Best Linux Distros for Gaming in 2021
The Linux operating system has come a long way from its original, simple, server-based look. This OS has immensely improved in recent years and has no...
Linux'ta oyun oturumunuzu nasıl yakalar ve yayınlarsınız?
Geçmişte oyun oynamak sadece bir hobi olarak görülüyordu, ancak zamanla oyun endüstrisi teknoloji ve oyuncu sayısı açısından büyük bir büyüme gördü. Ç...