calloc() ile Bellek Ayırma
Coddy'nin C Journey'sinin Logic & Flow bölümünün bir parçası — ders 36 / 63.
malloc() dinamik bellek ayırma için en yaygın fonksiyon olsa da, C başka bir kullanışlı alternatif sunar: calloc(). "Bitişik ayırma" (contiguous allocation) anlamına gelen calloc() fonksiyonu, önemli bir ek avantajla birlikte diziler için bellek ayırmanın kolay bir yolunu sunar.
Tek bir argüman (toplam bayt) alan malloc() fonksiyonunun aksine, calloc() iki argüman alır: tahsis etmek istediğiniz eleman sayısı ve her bir elemanın boyutu. Bu, özellikle dizilerle çalışırken onu sezgisel hale getirir. Örneğin:
#include <stdlib.h>
// calloc() kullanarak 5 tam sayı için yer ayırın
int *arr = (int*)calloc(5, sizeof(int));
// Bu şuna eşdeğerdir: malloc(5 * sizeof(int))calloc() fonksiyonunun temel avantajı, ayrılan tüm belleği otomatik olarak sıfıra ilklendirmesidir. malloc() kullandığınızda, ayrılan bellek daha önce orada saklanan rastgele değerleri içerir, ancak calloc() her baytın sıfıra ayarlanmasını garanti eder. Bu, tüm tamsayıların 0, tüm kayan noktalı sayıların 0.0 ve tüm işaretçilerin NULL olacağı anlamına gelir.
malloc() gibi, calloc() da ayrılan belleğe bir işaretçi döndürür veya ayırma başarısız olursa NULL döndürür; bu nedenle her zaman ayırma hatasını kontrol etmeli ve kullanmayı bitirdiğinizde belleği free() etmeyi unutmamalısınız.
Görev
KolayOtomatik sıfır başlatma ile dinamik bellek tahsisi için calloc() kullanımını gösteren bir C programı yazın. Programınız şunları yapmalıdır:
- Kullanıcıdan tahsis edilecek tam sayı adedini temsil eden bir
sizetam sayısı okuyun sizeadet tam sayıdan oluşan bir dizi için dinamik olarak bellek tahsis etmek üzerecalloc()kullanın- Bellek tahsisinin başarılı olup olmadığını kontrol edin - başarısız olursa,
Memory allocation failed!yazdırın ve programı sonlandırın - Tahsis başarılı olursa,
Memory allocated and initialized to zero!yazdırın - Dizideki tüm başlangıç değerlerinin sıfır olduğunu göstermek için şu formatta yazdırın:
Initial values: [value1] [value2] [value3] ... - Kullanıcıdan
sizeadet tam sayı değeri okuyun ve bunları tahsis edilen dizide saklayın - Tüm güncellenmiş değerleri şu formatta yazdırın:
Updated values: [value1] [value2] [value3] ... - Tüm değerlerin toplamını hesaplayın ve şu formatta yazdırın:
Sum: [value] - Belleği serbest bırakmak için
free()kullanın - Temizliği onaylamak için
Memory freed!yazdırın
calloc() ve free() kullanmak için <stdlib.h> başlık dosyasını dahil etmeyi unutmayın. Bu zorluk, calloc()'un malloc()'a göre temel avantajını gösterir: tahsis edilen tüm belleğin otomatik olarak sıfıra başlatılması.
Örneğin, giriş şu şekildeyse:
3
10 20 30Çıktınız şu şekilde olmalıdır:
Memory allocated and initialized to zero!
Initial values: 0 0 0
Updated values: 10 20 30
Sum: 60
Memory freed!Bu zorluk, calloc()'un dinamik olarak tahsis edilen dizileriniz için nasıl temiz ve öngörülebilir bir başlangıç durumu sağladığını, malloc()'un geride bırakabileceği öngörülemeyen çöp değerleri (garbage values) nasıl ortadan kaldırdığını vurgular.
Kopya kağıdı
calloc() fonksiyonu, otomatik sıfır ilklendirmesi ile dinamik bellek tahsisi sağlar.
Sözdizimi:
void* calloc(size_t num_elements, size_t element_size);malloc() fonksiyonundan temel farklar:
- İki argüman alır: eleman sayısı ve her bir elemanın boyutu
- Tahsis edilen tüm belleği otomatik olarak sıfıra ilklendirir
- Dizi tahsisi için daha sezgiseldir
Örnek kullanım:
#include <stdlib.h>
// calloc() kullanarak 5 tam sayı için yer ayır
int *arr = (int*)calloc(5, sizeof(int));
// Bu şuna eşdeğerdir: malloc(5 * sizeof(int))
// Ancak tüm değerlerin 0 olması garanti edilirmalloc() gibi, calloc() da tahsis edilen belleğe bir işaretçi döndürür veya tahsis başarısız olursa NULL döndürür. Her zaman tahsis hatasını kontrol edin ve işiniz bittiğinde belleği serbest bırakmak için free() kullanın.
Kendin dene
#include <stdio.h>
#include <stdlib.h>
int main() {
int size;
// Dizinin boyutunu oku
scanf("%d", &size);
// TODO: Kodunuzu aşağıya yazın
// Dizi için bellek ayırmak üzere calloc() kullanın
// Bellek ayırma işleminin başarılı olup olmadığını kontrol edin
// Başlangıç değerlerini yazdırın (sıfır olmalı)
// Giriş değerlerini okuyun ve saklayın
// Güncellenmiş değerleri yazdırın
// Toplamı hesaplayın ve yazdırın
// Ayrılan belleği serbest bırakın
return 0;
}Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Logic & Flow bölümündeki tüm dersler
1Pointer Temelleri
Pointer Nedir?Pointer TanımlamaAdres Operatörü (&)Dereference Operatörü (*)NULL Pointer'larÖzet: Pointer Temelleri4Proje: Basit Metin Aracı
Projeye Genel BakışKarakter Sayma2İşaretçiler ve Diziler
İşaretçi Olarak Dizi İsimleriDizi Elemanları - İşaretçilerİşaretçi Aritmetiğiİşaretçilerin KarşılaştırılmasıÖzet: İşaretçi ile Dizi Gezinme5İşaretçiler ve Fonksiyonlar
Değer ile GeçmeFonksiyonlara İşaretçi Göndermeİşaretçiler ile Değişkenleri DeğiştirmeKlasik Bir Örnek: SwapFonksiyonlara Dizi GöndermeÖzet: Fonksiyon İşaretçi Argümanları8Yapılar ve İşaretçiler
Yapılara İşaretçilerOk Operatörü (->)Yapıları Değer ile AktarmaYapı İşaretçilerini AktarmaYapıların Dinamik TahsisiÖzet: Yapıyı Değiştirme - Ptr11Son Tekrar Görevleri
Tekrar: Dinamik String BirleştirmeTekrar: Struct DizisiTekrar: Kelime Frekans Sayacı3Karakter Dizileri ve Stringler
char Dizisi Olarak StringlerNull Sonlandırıcıscanf ile String Girişistrlen() Kullanımıstrcpy() Kullanımıstrcat() Kullanımıstrcmp() KullanımıÖzet: Temel String Fonksiyonları