Merhaba, tekrar hoş geldiniz. Bu derste nokta aritmetiği hakkında konuşmak istiyorum.
Artık diziler ve işaretçiler arasındaki ilişkiyi anladığımıza
göre, bu kavramı anlamak daha kolay olacaktır.
Aritmetik diyoruz, ama aslında demiyoruz -- gerçekte
tüm anlamı, bir işaretçinin kendisi üzerinde artı
veya eksi ya da artırma veya azaltma yapabileceğinizdir.
Dolayısıyla, dizilere işaretçi kullanmanın gerçek gücü, bir dizinin öğeleri arasında sıralama
yapmak istediğinizde ortaya çıkar.
İlk öğeden sonuna kadar gitmek istiyorsunuz, bunlar arasında yineleme yapmak istiyorsunuz.
İşte gerçek güç göstericileri. İşaretçiler adresleri kullandığından,
dizideki her öğe başka bir adrestir.
Böylece işaretçilerde sadece artı artı yapabilir ve bir sonraki adrese gidebilirsiniz.
Yani burada values pointer, values dizisinin ilk tamsayısına erişmek
için kullanılabilir.
0'ın altındaki değerlere erişmek için kullanılabilir.
Değer işaretçisinin bir tamsayı dizisine işaret eden bir işaretçi
olduğunu hatırlarsanız.
Ve dizideki ilk elemana sadece dizi adına işaretçi atayarak atadık.
İstersek sub-0 operatörünün adresini de kullanabiliriz.
Ancak, dizideki ilk elemana işaret ettiği için
değer işaretçisinin referansını kaldırdığımızda,
size değer alt-0 dizisindeki ilk tamsayıyı verecektir.
İşaretçi değişken aracılığıyla alt 3 değerine başvurmak
isterseniz, yapmanız gereken tek şey değer işaretçisine 3 eklemek ve ardından referansı kaldırmak
için dolaylama operatörünü uygulamaktır.
Yani şöyle bir şey yapabilirsiniz. Değer işaretçisi artı 3 diyebilir ve ardından yıldız işaretiyle
referansını kaldırabilirsiniz.
Ve bunu netleştirmek için genellikle tırnak işaretlerinin dışına yıldız işareti koyarsınız.
Ancak bunun yaptığı şey, dizideki ilk
öğenin adresi olan values pointer'a 3 eklemektir.
Ve böylece aslında tamsayılar için her baytı toplayacak, baytları
tamsayılarla çarpacaktır.
Ancak bu aslında alt 3'e, dizideki
4. öğeye işaret edecektir.
Yani ifadede asterisk values pointer plus i, bir values dizisinde
bulunan herhangi bir değere erişmek için kullanılabilir.
Yani bu ifadeyi anlarsanız, i'ye herhangi bir şey ekleyebilirsiniz ve bu sizi
belirli bir eleman dizisine yönlendirecektir.
Yani 10'un altındaki değeri 27'ye ayarlamak istiyorsanız, tek
yapmanız gereken bir işaretçi kullanıyorsanız, işaretçi
artı 10 değerini söylemek ve ardından bunu kaldırıp eşittir 27 demek.
Burada farklı bir söz dizimi görüyorsunuz.
Yine, notasyonel kolaylık ama aynı zamanda programın kendisi açısından daha verimli.
İşaretçiler dizilerle çok yakından ilişkili oldukları için, işaretçileri
artırıp azaltarak ya da bir işaretçiye değer ekleyerek veya ondan değer
çıkararak öğelere kolayca erişebilirsiniz.
Çok, çok faydalı.
values pointer öğesini values dizisinin ikinci öğesini gösterecek şekilde ayarlamak için,
adres operatörünü value sub 1 öğesine uygulayabilir ve sonuçları values pointer öğesine atayabilirsiniz.
Bunu gördük. Bu, adres alt operatörünü kullanmak istiyorsanız daha
önce bahsettiğim aynı şeyi yapmanın başka bir yoludur.
İsterseniz bunu her zaman yapabilirsiniz,
ancak işaretçi aritmetiği yapmak çok daha kullanışlıdır.
Eğer values işaretçisi sub-0 değerine işaret
ediyorsa, values işaretçisinin değerine bir ekleyerek bir değerine
ayarlayabilirsiniz. Nokta aritmetiği ile ulaşmaya çalıştığımız şey de budur.
Tek yapmanız gereken values point veya plus equals
one demek ve artık values pointer dizideki ikinci elemana veya ilk indekse
işaret ediyor.
Çok, çok güzel bir notasyon, yapması çok kolay.
Dolayısıyla bu, c'de mükemmel bir şekilde geçerli bir ifadedir
ve ister tamsayı ister karakter olsun, herhangi bir veri türüne işaretçiler
için kullanılabilir. Ve muhtemelen bunun karakterlerde ne kadar yararlı olabileceğini düşünmelisiniz.
Bir karakter işaretçiniz varsa, artık bir işaretçi üzerinde artı
işareti yaparak bir dizedeki her bir öğeye, her bir karaktere erişebilirsiniz.
Artırma ve azaltma operatörleri artı artı ve eksi eksi, bu
işaretçilerle çalışırken özellikle kullanışlıdır
çünkü genellikle bir elemandan diğerine gitmek isteyeceksiniz.
Genellikle sırayla gittiğiniz için 22 veya eksi 20
eklemek o kadar yaygın değildir.
Bu nedenle, bir işaretçide artırma operatörünü kullanmak, işaretçiye bir eklemekle aynı etkiye sahiptir.
Azaltma operatörünün kullanılması, işaretçiden bir çıkarılmasıyla aynı etkiye sahiptir.
Yani artı artı değerler işaretçisi demek, değerler işaretçisini
değerler dizisindeki bir sonraki tamsayıyı gösterecek şekilde ayarlayacaktır.
Eksi eksi olmalıdır değerler işaretçisi Değerler dizisindeki
bir önceki tamsayıya işaret eden değerler işaretçisini ayarlayacaktır.
Ancak eksi eksi yaparken dikkatli olmak istersiniz çünkü
en azından dizide olduğunuzdan ve 0'da olmadığınızdan emin olmak istersiniz.
Aynı şey artı artı için de geçerli.
Dizinin sonuna geldiyseniz, herhangi bir sınır dışı hatası almak istemezsiniz.
Bu nedenle, değer işaretçisini azaltıyorsanız, başlangıçta
değerler dizisinin başlangıcını işaret etmediğinden emin olun.
Burada, dizideki tüm elemanları
toplayacağımız bir başka örnekte, bir dizi toplamı
fonksiyonumuz olduğunu ve fonksiyonun bir
dizi aldığını ve ayrıca parametre olarak
sabit bir tamsayı aldığını görüyorsunuz.
Fonksiyonun içinde bir tamsayı oluşturacağız.
Bu tamsayı toplamını 0 olarak başlatacağız ve int türünde bir tamsayı
işaretçisi oluşturacağız.
Ayrıca sabit bir işaretçi de oluşturacağız.
Yani bu, adresini değiştiremeyeceğiniz anlamına geliyor.
Her zaman dizi artı n olacak ve dizi sonu olarak adlandırılacaktır.
Bunu yapıyoruz çünkü dizinin sonuna gidip sadece işaretçiye bakacak
şekilde ayarlarsak döngümüzü daha verimli hale getiriyoruz.
Yani dizi sonu, dizinin sonunun adresine işaret eder.
Dizi diyebiliriz, bu da aktarılan şeydir ve sonra
n, dizinin boyutu, boyutudur.
Şimdi for döngüsü, diziye bir işaretçi olan döngü kontrol değişkeni
işaretçisini başlatacaktır. Ve eğer bir dizinin ilk elemanına
bir işaretçi atamak istiyorsanız, tek yapmanız gereken işaretçi
eşittir dizi demek.
Ve sonra döngü çıkış koşulumuz, işaretçinin dizi sonundan küçük olmasıdır.
Unutmayın, bir işaretçi bir adrestir ve dizi sonu da bir adrestir.
Yani pointer'daki adres n pointer'ından küçükse döngünün gövdesini çalıştırmak
istediğimizi söylüyoruz.
Pointer sadece bir tamsayıdır, onaltılık bir adrestir.
Her artırdığımızda bir sonraki adrese gider. Bitiş adresimiz var, bu yüzden sona ulaşana
kadar döngü boyunca ilerle diyebiliriz.
Ve sonra işaretçinin kendisini artırıyoruz, bu
da esasen dizideki bir sonraki öğeye gitmek için adresi artıracak
çünkü işaret ettiğimiz şey bu.
Sonra döngümüzün gövdesi içinde, toplam artı eşittir işaretçisi deriz.
Değeri almak için işaretçiyi dereferanslıyoruz
çünkü değeri almak istediğimizi hatırlayın, işaretçinin adresini veya
işaretçinin işaret ettiği adresi almak istemiyoruz.
Ve en sonunda, toplamı döndürüyoruz. Yani bu, bir dizideki tüm
öğeleri toplayacaktır.
Main'de, dosyanın üst kısmının aksine orada da bir fonksiyon bildirimi
yaptığımızı fark edeceksiniz. Ben genellikle bunları dosyanın en üstüne koymayı tercih ederim.
Ancak ana dizide 10 elemanlı bir dizi oluşturuyoruz, 3 7 negatif 9 ve benzeri.
Daha sonra diziyi veya toplamı iletiriz ve boyutu
10 olarak belirtiriz.
Ve fark edeceğiniz şey, dizinin toplamı olan değeri döndürmesidir.
Bu nedenle, bir dizi içinde yineleme yapmak için bu nokta aritmetiğini kullanmak çok, çok
güzeldir, sadece bir sonraki
adrese artı yapabiliriz ve ayrıca atlamak için bitiş adresine bakabiliriz.
Bu, n'den daha azına bakan bir sayaç yerine bitiş adresine
bakan işaretçi ile daha verimlidir.
Ayrıca bunları sabitler olarak oluşturduğumuzu fark etmişsinizdir çünkü sabitler
değişmez ve bu derleyici için daha verimlidir.
Buradaki dizi sabit bir işaretçidir, yani adres değişemez.
Bu örnekte, bir diziyi bir fonksiyona aktarmak
için sadece dizinin adını belirtmeniz gerektiğini de fark etmiş olmalısınız.
Böylece fonksiyonu nasıl yükselteceğimizi biliyoruz. Ve bir diziye işaretçi üretmek için yalnızca
dizinin adını belirtmeniz gerekir.
Dizinin ilk elemanını bir işaretçiye atadığımızda bunu gördük.
Yani bu, dizi toplamı işlevine yapılan çağrıda, işleve aktarılan
şeyin aslında dizi değerlerine bir işaretçi olduğu anlamına gelir.
Bu da size dizilerin ve işaretçilerin birbirleriyle çok yakından ilişkili olduğunu, bir dizinin
işaretçiden başka bir şey olmadığını gösterir.
Bu da bir dizinin elemanlarını neden bir fonksiyonun içinden değiştirebildiğinizi açıklar.
Çünkü bu noktaya kadar, bir fonksiyona veri aktardığınızda, bu veri bir işaretçi
olmadığı sürece fonksiyon dışında değiştirilmez.
Çünkü bu yüzden scanf için adres girmemiz gerekiyor.
Öğelerin bir işlevin dışında değiştirilmesinin tek yolu, işaretçileri
bir işleve geçiriyor olmanızdır.
Ve öğeler bu işlevin içinde değiştirildiği için, bu bir işaretçi
geçirdiğiniz anlamına gelir.
Bu da dizilerin ve işaretçilerin çok ama
çok benzer olduğunu, dizilerin aslında sadece farklı sözdizimi kullanan işaretçiler olduğunu
bir kez daha kanıtlıyor.
Referansla nasıl geçebileceğimizden ya da bir referansın kopyasını nasıl geçirebileceğimizden
bahsedeceğiz, bu da bir işlevdeki verileri o işlevin
dışında değiştirmenize olanak tanıyacaktır.
Önceki görevlerimizden birinden hatırlarsanız,
bir fonksiyondaki verileri değiştirmek istediğimizde global bir değişken
kullanmamız gerekiyordu.
Çünkü referansla geçiş kavramını
ve işaretçi kavramını anlamamıştık.
Ancak daha önce de belirttiğim gibi, işaretçilerin avantajlarından biri
de artık bir işlevin içindeki verileri değiştirebilmeniz ve bunun işlevin dışına yansıtılmasıdır.
Ama bu başka bir ders konusu.
Ancak bu kavramın kendisi, bir önceki örnekte dizilerin esasen nasıl işaretçi
olduğunu göstermektedir.
Bu nedenle, işlev içindeki resmi parametrenin neden bir işaretçi olarak bildirilmediğini merak edebilirsiniz.
Olabilir. Şöyle bir şey yapabiliriz: int dizi toplamı, int yıldız dizisi.
Bunu bir dizi olarak bildirmemize gerek yok.
Bu tamamen geçerlidir çünkü diziler ve işaretçiler aynıdır, int star array diyebiliriz.
Çok yakın akraba olduklarından bahsetmiştik.
Böylece, dizi toplamı işlevi içinde bir dizi türünü int türünde bir dizi olarak
bildirebilir veya int türünde bir gösterici olarak bildirebilirsiniz.
İşte bu yüzden dizileri parametre olarak ya da parametrelerin aslında işaretçi olduğu argümanlar
olarak kabul eden birçok fonksiyon görürsünüz.
Dolayısıyla, bir işleve aktarılan bir dizinin öğelerine başvurmak için dizin numaralarını kullanacaksanız,
parametreyi bir dizi olarak bildirin.
Yine notasyonel kolaylık, sadece parantez ve alt simge kullanarak
veya bir işaretçi kullanarak notasyonun farklı bir yoludur.
Dizinin kendisi genellikle programın bakımı açısından
daha kolay okunur ve dizinin işlev tarafından kullanımını daha doğru yansıtır.
Ancak işaretçinin kullanımı daha kolaydır.
Ve diziye işaretçi olarak bir argüman kullanıyorsanız, resmi parametrede bunun işaretçi
türünde olduğunu bildirin.
İşte bir önceki örnekte dizi gösteriminin kullanıldığı yerde
fonksiyonun işaretçi gösterimiyle bir örnek.
Burada sadece int start array diyoruz
ve fark edeceğiniz şey, fonksiyonun hemen çok daha küçük hale
geldiğidir, çünkü diziye işaretçiyi yaptığımız gibi ilk elemana atamak
zorunda değiliz.
Döngü de çok daha küçük hale gelir çünkü ilk ifadede
bu atamayı yapmamız gerekmez.
Sadece dizi dizi sonundan küçük olana kadar diyebiliriz ve diziyi
artırabiliriz. Yani biraz daha az kod var, yine
de dizileri ve işaretçileri anlıyorsanız ne olup bittiği çok açık.
int yıldız dizisini geçiyoruz ve artık bu
diziyi başlatmamız gerekmiyor çünkü işaretçiyi geçiyoruz,
artık işaretçiyi başlatmıyoruz.
Ve sonra aslında dizinin sonunun adresini sabit bir
işaretçiye, dizi sonuna
ayarlıyoruz. Bunu döngüden çıkmak için kullanırız
ve sadece toplam artı eşittir yıldız dizisi deriz, diziye tekrar
referans vermek için dolaylama operatörünü kullanırız ve toplamı döndürürüz.
Ve sonra main işlevi, bildirimin artık bir dizi yerine bir işaretçi olması dışında tamamen aynıdır.
İşte farklı gösterimler kullanan ancak aynı işlevselliği sağlayan 2 örnek ve bu yüzden
bir fonksiyon parametresinin içinde parametre olarak çok sayıda işaretçi
görüyorsunuz.
Özetlemek gerekirse, burada işaretçi kullandığınızda geçerli olan ve
geçerli olmayan bazı şeyler vardır.
Burada bazı değişkenler bildirirsek, earn adında bir dizi bildiririz
ve 3 eleman içerir ve sonra 2 işaretçi bildiririz.
Şimdi bu işaretçiler üzerinde aritmetik yapabiliriz. İşaretçi bir artı artı diyebiliriz.
Nokta veya 2 eşittir nokta veya bir artı 2 diyebiliriz.
Hatta işaretçi 2 eşittir kazanç artı bir diyebiliriz.
Bunu yapmak tamamen geçerlidir çünkü işaretçileriniz vardır ve işaretçileri adrese göre değiştirirsiniz,
böylece nokta aritmetiği yapabilirsiniz.
Diziler üzerinde nokta aritmetiği yapamazsınız. Yani artı artı kazan diyemezsiniz.
Pointer 2 0 diyemezsiniz. 2 artı 0. 1 çünkü bunlar
adreslerdir.
Ve aslında bir dizinin içindeki herhangi
bir şeye işaret etmiyorsunuz.
Ve puan veya 2 elde etmek için puan veya bir ile çarpamazsınız.
Bunlar geçersiz.
Bu nedenle, işaretçi aritmetiği için doğru sözdizimine dikkat edin
ve ayrıca nokta aritmetiğinin dizilere değil, yalnızca işaretçilere uygulanabileceğini
anlayın.
Ayrıca dizileri işleyen işlevler aslında argüman olarak işaretçileri kullanır.
Dizi işleme işlevlerini yazmak için dizi gösterimi ile işaretçi gösterimi
arasında seçim yapabilirsiniz.
Dolayısıyla, rastgele işlevi işleyecekseniz, parametre olarak bir işaretçi kullanmanızda bir sakınca yoktur.
Hangisini kullanmak istediğinizi seçebilirsiniz.
Ancak işaretçi kullanmak genellikle daha az kod ve daha verimlidir.
Dizi gösterimini kullanmak, fonksiyonun dizilerle çalıştığını daha belirgin hale
getirir ve dizi gösterimi, belirli dillerde biraz programlama geçmişi olan programcılar
için daha tanıdık bir görünüme sahiptir.
Dolayısıyla, daha önce Fortran, Pascal ve benzerlerini programladıysanız,
ok gösterimini kullanabilirsiniz.
Diğer programcılar işaretçilerle çalışmaya daha alışkın olabilirler ve işaretçi gösterimini
daha doğal bulabilirler, sadece daha mantıklıdır.
Nokta aritmetiği ve işaretçi gösterimini kullanarak makine
diline daha yakındır ve bazı derleyicilerle daha verimli kodlara yol açar, bu da onu kullanmak
için başka bir nedendir.
Şimdi bu örneklere kod blokları içinde bir
göz atalım.
İşte slaytlardaki örneğimiz. Fonksiyon bildirimimiz 3. satırda yer almaktadır.
Bu bir dizi toplamı.
Ve bu örnekte, dizi gösterimini kullanacağız.
Bu yüzden dizinleri kullanırken parantezleri kullanacağız.
Ve bunu değerler dizisini girerek
ve boyutu girerek çağıracağız.
Yani dizi toplamı işlevi bir tamsayı dizisi alır. Yapmanız gereken ilk şey, 14. satırda
nokta aritmetiği için kullanmak istediğiniz işaretçiyi
oluşturmaktır. Ve sonra dizinin sonunu adres dizisine
artı boyut olarak atamanız gerekir.
Bu, artık döngüden çıkmak için kullanabileceğiniz dizinin sonudur.
Ancak işaretçiyi diziye atamamız gerekir.
Dizileri, sadece dizinin adını kullanarak ilk elemanı
gösterecek şekilde işaretçilere atayabileceğimizi biliyoruz.
Operatif adresini kullanmak zorunda değiliz.
Eğer isteseydik, gerçekten böyle bir şey yapabilirdik.
Ve bu da iyi.
Ve sonra artı artı işaretçi. İşaretçiyi artırıyoruz çünkü tek yaptığı
bir sonraki adrese artırmak. Dizideki bir sonraki öğeye işaret eder.
Ve sonra 18. satırda, toplamı hesaplamak için işaretçinin referansını kaldırıyoruz,
toplam eşittir, toplam artı işaret ettiği işaretçinin değeri.
Bunu oluşturduğumuzda bir uyarı alıyoruz, main bir int değil,
bunu değiştirmek istiyoruz çünkü main'den
hata değerleri döndürmek ve sadece return 0
demek iyidir.
Eğer main'de bir hata varsa, negatif
bir hata döndürürsünüz. Şimdi bunu çalıştırdığımızda, sadece dizideki değerlerin toplamını
gerçekleştirdiğini göreceksiniz, yani 3 artı 7 artı negatif 9 ve benzeri, bunun ne olduğundan
bile emin değilim ama 21 gibi görünüyor.
Şimdi bu dizi parametresini, sadece işaretçiden önce yıldız işaretini
bildirerek bir işaretçi alacak şekilde kolayca değiştirebiliriz.
Biz de aynı şekilde diyoruz. Sadece modifiye ediyoruz. Artık işaretçiyi bildirmemize
gerek yok. Muhtemelen daha kolay olması için
adını değiştirmek istiyoruz, ancak artık bu işaretçiyi bildirmemize gerek yok.
Hala dizinin sonunu almak istiyoruz ve
artık onu atamamıza da gerek yok.
Oraya boş bir şey koyabiliriz. Ve aslında burada bir while döngüsü olması daha faydalı olabilir.
Ancak atamamız yoksa noktalı virgülü oraya koyabiliriz.
Ve şimdi iyiyiz. Yine de referansı kaldırmak ve geri döndürmek istiyoruz.
Ancak bunu inşa edersek,
değiştirdiğimiz için fonksiyon
bildirimini bir işaretçi olarak tanımladığımızdan emin olmak isteriz.
Ve bu herhangi bir isim olabilir ama biz sadece tutarlı olacağız.
Şimdi, değiştirdiğimiz
tüm değişkenleri tekrar kullandığımızdan emin
olmak istiyoruz.
Şimdi başarılı bir şekilde oluşturduk, çalıştırdık ve 21 olan
aynı sonucu elde ettiğinizi görüyorsunuz.
Bu nedenle, işaretçileri dizilerde resmi parametreler olarak kullanmak arasındaki bu farkı anlayın,
bunları birbirinin
yerine kullanabilirsiniz. Bu sadece notasyonel bir kolaylık.
Ancak bir işaretçi kullandığınızda genellikle daha az kodunuz olur.
Ve onu daha fazla manipüle edebilir ve daha güçlü şeyler yapabilirsiniz, derleyiciye
bağlı olarak genellikle daha verimlidir. Teşekkür ederim.