Merhaba, tekrar hoş geldiniz. Bu derste, malloc kullanarak belleği
dinamik olarak nasıl
ayıracağınızı anlamanızı sağlayan bir önceki zorluğumuz
için bir gösteri sunmak istiyorum.
Sadece klavyeden basit bir okuma yapacağız ve ardından bir dizeyi
görüntüleyeceğiz, ancak bunu dinamik olarak ayrılmış
işaretçilerle, karakter işaretçileriyle kullanacağız.
Öyleyse kod bloklarını getirelim yeni bir proje oluşturalım.
Ve bu örneğe sadece dinamik bellek tahsis örneği adını vereceğiz.
Dinamik bellek tahsisini kullanacağınız
zaman yapmanız gereken ilk şey, standart lib'i dahil ettiğinizden emin olmanızdır.
Neyse ki kod bloklarında bir proje oluşturduğunuzda, bunu sizin
için otomatik olarak ekleyecektir.
Ancak standart lib'i dahil etmemizin nedeni malloc işlevinin
orada olmasıdır. Ve malloc, hatırlayın, bellek
ayırmak için ana işlevdir. Ayrıca calloc da var.
Calloc gerçekten önemlidir çünkü calloc
kaç byte'a ihtiyacınız olduğunu güzel bir şekilde hesaplar
çünkü bu iki parametredir.
Ancak calloc'un asıl iyi yanı, eğer ints ve benzeri şeylerse tüm verileri
sıfıra başlatmasıdır, gerçekten güzel bir işlevdir.
Yeniden tahsis ettiniz. Realloc zaten ayrılmış olan belleği
genişletir. Yani onu bir işaretçi içinde geçirirsiniz.
Bu işaretçiden, onun için ne kadar bellek ayrıldığını belirler
ve orada bulunan her şeyi yeni bir bellek konumuna kopyalar ve sonra
kaç bayt daha ayırmak istediğinizi de belirtirsiniz,
sadece yeni bellek konumuna ekler, gerçekten güzel bir özellik.
Ancak malloc kullanarak tamsayılar için bellek ayırırken, bayt olarak ne kadar bellek
ayırmak istediğinizi belirlemeniz gerektiğini unutmayın, ancak genellikle
sizeof operatörünü kullanmak istersiniz.
Şimdi buna geçelim.
Ana yöntemimde, bir tamsayı oluşturacağım ve bunun sadece
boyut olacağını söyleyeceğim. çalışma zamanında kaç bayt ayırmak istediklerinin
boyutunu girecek, böylece bu boyutu saklayacaktır.
Oluşturmak istediğim diğer şey ise bir char pointer oluşturmak istiyorum
ve bu sadece metin olacak. Ve bunu null olarak başlatacağım
çünkü başlangıçta hiçbir şeye işaret etmiyor.
Şimdi yapmak istediğim ilk şey, kullanıcıdan boyutu girmesini istemek.
Bu yüzden printf diyeceğim,
metnin sınırını girin diyeceğim.
Ve kaç baytın gerçekten karakter sayısı olarak tahsis edilmesini istediklerine
dair bir sayı girecekler.
Ve sonra scanf kullanarak bunu okuyacağım.
Scanf, ilk parametre verinin türü için biçim belirticisinin türüdür.
Bu yüzde d olacak çünkü bir tamsayı okuyorum.
Ve unutmayın, scanf bir işaretçi alır.
Artık işaretçi alan fonksiyonların
bir adrese ihtiyaç duyduğunu biliyoruz.
Bu nedenle, size değerini geçeceksem, operatörün adresini kullanmadığım sürece size bir adres değildir.
Bu yüzden ve işareti koyacağım ve boyut
diyeceğim, bu bayt sayısını okuyacak.
Bayt sayısını öğrendikten sonra, malloc fonksiyonunu kullanarak bunun için bellek ayırabilirim.
Ve malloc bir void pointer döndürecektir.
Ve işaretçi, yeni tahsis edilen belleğin
ilk adresi olacaktır. Böylece doğrudan metne atayabilirsiniz.
Çünkü unutmayın, metin bir işaretçidir.
Metni, döndürülen bu yeni adrese yönlendirmek istiyoruz.
malloc bir void işaretçi döndürdüğü için, onu cast etmemiz gerekir.
İşaret ettiğimiz veri türü bir karakterdir, bu nedenle char star demek istiyoruz
ve ardından malloc işlevini çağırabiliriz.
malloc işlevi bayt sayısını alır.
Dolayısıyla, bayt sayısını girerseniz, yalnızca o kadar
bayt ayıracaktır. Ancak verinin türüne bağlı olarak,
verinin türü iki veya dört bayt olabilir.
Yani 10 karakter ayırmak istiyorsanız,
10 karakteri char boyutuyla çarptığınızdan
emin olmak istersiniz.
Şimdi n kere sizeof
diyeceğiz. Sizeof operatörü malloc fonksiyonunda sıklıkla
kullanılır çünkü makineden bağımsızdır ve
size gerçekte ne kadar ayırmanız gerektiğini söyleyecektir.
Şimdi bu, tam sayılar olduğunda daha önemlidir. Unutmayın, tamsayılar, üzerinde
çalıştığınız sisteme, mimariye bağlı olarak, dört
bayt, iki bayt, genellikle iki veya dört bayt ile temsil
edilebilir.
Bir tamsayı saklamak istiyorum, bu yüzden sadece
dört baytlık bellek oluşturacağım derseniz, bu doğru olmayabilir
çünkü ya iki baytsa.
Dolayısıyla, her zaman kaç tam sayı
veya kaç karakter oluşturmak istediğinizi belirlemek ve ardından bunu sisteminizdeki
karakter boyutuyla çarpmak istersiniz. Sizeof işleci size bir char karakterin kapladığı
bayt sayısını verecektir. Yani 10 karakter oluşturmak istiyorsanız,
karakter boyutunun 10 katını söylersiniz. Eğer 10 tamsayı saklamak için 10
tamsayı oluşturmak istiyorsanız,
int boyutunun 10 katı dersiniz, bu gerçekten önemlidir.
Şimdi calloc fonksiyonu ile bunu yapmak zorunda değilsiniz. Calloc aslında iki
parametre alır. İlk parametre sanırım
işaretçidir ve ardından ikinci
parametre bayt boyutudur.
Yani 24 int derseniz, tek yapmanız gereken sadece 24'ü girmektir ve otomatik
olarak sizin için tahsis edilir.
Dolayısıyla calloc kullanmak için gerçekten güzel bir araçtır çünkü bu çarpma işlemini yapmak zorunda kalmazsınız.
Yani calloc için ilk parametre boyuttur.
Yani 10 int oluşturmak istiyorsanız, sadece 10 değerini girersiniz.
İkinci parametre ise
baytın boyutudur. Yani çarpma işlemi yapmanıza gerek yok. Sizi adımdan biraz kurtarır.
Bellek ayırdığımıza göre, metni referans
dışı bırakmaya çalışmadan önce metnin null olmadığından emin olmak istersiniz.
Dolayısıyla, bunu her zaman bir not text'in etrafına sarmak istersiniz ve bu,
null olmadığını söyleyecektir veya sadece açıkça yapabilir ve if text
is not equal to null diyebilirsiniz.
Bunu her zaman yapmak isterim çünkü bir işaretçiyi referans
dışı bırakmaya çalışmak çok ama çok tehlikelidir.
Her şey olabilir. İçine veri yazabilirsiniz.
içine. Sadece hafızada başka bir yere yazacaktır. Bu yüzden programınızı
mahvedebilir veya bir segmentasyon hatası yaşayabilirsiniz ve program çökebilir.
Ancak bu belleği gerçekten ayırdığınız sürece, artık
bazı verileri gerçekten okuyabilirsiniz.
Burada git s ya da scanf kullanabilirsiniz.
Ancak yapmak istediğiniz şey çıktı
almak, bazı metinler girmek ve okunması
kolay olsun diye buraya satır beslemeleri eklemektir.
Ve aşina olduğumuz için scanf kullanacağız.
Ve scanf sadece yüzde olarak okuyacak.
Aslında, sana bir numara göstereceğim.
Bir sonraki karakteri okumak için scanf kullanacağım, böylece
duraklayacak ve sonra metni okumak için get s kullanacağım.
gets ise genellikle f gets'i kullanabileceğiniz başka bir fonksiyondur. Bunu sadece giriş akışına ayarlamanız
gerekir.
Ancak gets, varsayılan olarak klavye olan standart giriş akışından okuyacaktır.
Ve gets bir işaretçi alacak. Böylece tek yapmamız gereken metni geçmektir, çünkü
bu zaten bir işaretçidir, operatörün adresini girmemize gerek yoktur.
Get sorgularının güzel yanı, boşluklarla ayrılmış birden fazla dizeyi okuyabilmenizdir.
Bir kez gerçekten okuduğumuzda, sadece
çıktısını alabiliriz. Dolayısıyla, inputted bir kelime ise
inputted text yüzde s ters eğik çizgi n ve ardından
virgül text diyebiliriz. Metin bir işaretçidir.
Printf bir işaretçi alır. Referansı kaldırmamıza gerek yok.
Çünkü sadece metin görüntülerseniz, metin
bir adres olacak olan işaretçinin değerini görüntüleyecektir.
Aslında metnin işaret ettiği değeri görüntülemek istiyoruz.
Ve sonra işimiz biter. Hayır, kesinlikle işimiz bitmedi. Özgürlüğümüzü aramak istiyoruz.
İşaretçimizi serbest bırakmak istiyoruz.
Çıktığımızda bellek boş olacak olsa bile. Yine de onu serbest bıraktığımızdan emin olmak
istiyoruz ve sonra muhtemelen sadece güvenlik için text'i null'a eşit olarak ayarlamak istiyoruz.
O halde devam edip bunu inşa edelim ve ne olacağını görelim.
Ve bir sorunum var çünkü doğru değişkende
okumuyorum.
yani burada doğru değişkeni kullanmıyorum. Boyutu kullanmak istiyorum
ve görünüşe
göre sorun yok.
İşte buradaki tek fark, metin bir karakter işaretçisi olduğu için
metne referans vermek zorunda olmamanızdır.
Yalnızca işaretçi vb. içindeyse referansı kaldırmanız gerekir. Böylece yüzde s'yi kullandığınızda,
karakter işaretçisini otomatik olarak referans dışı bırakmayı
bilir.
Bu, karakter işaretçileri ile diğer işaretçileri kullanırken
ortaya çıkan bir farktır. Diğer işaretçilerde değeri
almak için referansı kaldırmanız gerekir, çünkü dizeleri
dize dizilerine vb. kopyalayamazsınız.
Asla yıldız metin eşitleme yapamazsınız, metni
kopyalamak istiyorsanız her zaman str copy kullanmanız gerekir.
Çünkü derslerden hatırlayacağınız üzere, bir diziye
veri atayamazsınız ve bir karakter işaretçisi bir dizidir.
Yani burada bu doğru görünüyor. Referansı kaldırmak için bir neden yok.
Bunu inşa etmek ve sonra da çalıştırmak istiyoruz.
Ve metnin sınırını koyduğumuzu fark edeceksiniz.
Diyelim ki jason için 5, 6 yazdık ve input is jason
çıktısını verdi.
Ve bu programla oynayabilirsiniz. Ancak yine de, malloc yaparken
standart lib'i kullanmayı da unutmayın.
Karakter işaretçilerinizi null olarak başlatın. Bir scanf yapın, ve işareti
kullanın çünkü size bir işaretçi değildir.
Malloc yaparken, malloc bir void işaretçi döndürür, bu nedenle döküm yapmanız gerekir.
Her zaman malloc'unuzun içinde olmak istersiniz. Tahsis etmek istediğiniz
şey için sizeof operatörünü kullanın. Times, kaç gerçek karakter olduğu
veya tam sayılar. Bu, teknik olarak karakterler için daha çok tamsayılar
ve ilkel veri türleri için geçerlidir. Sadece boyut yapabilirsiniz, bu işe yarayacaktır.
Her zaman null olup olmadığını kontrol etmek istersiniz, null olmadığından emin olun.
Karakter dizesini kullanmaya gittiğinizde.
Ve sonra sadece bazı metinler giriyoruz, bunları depoluyoruz ve yazdırıyoruz.
Ve son olarak, her zaman işaretçilerimizi serbest bırakmak isteriz, böylece bunu
yığına geri verebiliriz. Umarım bu yardımcı olur. Teşekkür ederim.