Yapıların Dinamik Tahsisi
Coddy'nin C Journey'sinin Logic & Flow bölümünün bir parçası — ders 48 / 63.
Şimdiye kadar, yığında (stack) struct'ların nasıl oluşturulacağını öğrendiniz - bunlar bildirildikleri kapsam (scope) içinde var olurlar ve bu kapsam sona erdiğinde otomatik olarak temizlenirler. Peki ya bir struct'ın orijinal kapsamının ötesinde kalıcı olmasına ihtiyaç duyarsanız veya derleme zamanında (compile time) kaç tane struct'a ihtiyacınız olacağını bilmiyorsanız?
İşte burada dinamik bellek ayırma devreye girer. Tıpkı diğer veri türlerinde yaptığınız gibi, heap üzerinde struct'lar oluşturmak için malloc() kullanabilirsiniz. Temel fark, dinamik olarak ayrılmış struct'ların, siz onları free() ile açıkça serbest bırakana kadar bellekte kalmasıdır.
Bir yapıyı (struct) dinamik olarak bellekten ayırmak için kullanılan sözdizimi şöyledir:
struct Point *ptr = malloc(sizeof(struct Point));Bu, bir Point yapısını (struct) tutmak için yığında (heap) yeterli bellek tahsis eder ve bu belleğe bir işaretçi (pointer) döndürür. Ardından, yapı üyelerine erişmek ve onları değiştirmek için ok operatörünü kullanabilirsiniz:
ptr->x = 10;
ptr->y = 20;Bellek sızıntılarını önlemek için her zaman malloc() fonksiyonunun başarılı olup olmadığını (NULL olmayan bir değer döndürdüğünü) kontrol etmeyi ve struct ile işiniz bittiğinde free(ptr) fonksiyonunu çağırmayı unutmayın. Bu teknik, çalışma zamanında veri yapıları oluşturabilen ve yönetebilen esnek programlar oluşturmak için gereklidir.
Görev
Kolaymalloc() kullanarak struct'ların dinamik olarak tahsis edilmesini gösteren bir C programı oluşturun. Programınız şunları yapmalıdır:
- Aşağıdaki üyelere sahip
Caradında birstructtanımlayın:- Üretim yılını saklamak için bir tamsayı
year - Araba markasını saklamak için 20 boyutunda bir karakter dizisi
brand - Araba modelini saklamak için 25 boyutunda bir karakter dizisi
model - Araba fiyatını saklamak için bir float
price - Arabanın kilometresini saklamak için bir tamsayı
mileage
- Üretim yılını saklamak için bir tamsayı
- Ana fonksiyonda,
carPtradında birCarstruct işaretçisi (pointer) bildirin - Bir
Carstruct'ı için dinamik olarak bellek tahsis etmek üzeremalloc()kullanın ve döndürülen adresicarPtrdeğişkenine atayın - Bellek tahsisinin başarılı olup olmadığını kontrol edin:
- Eğer
carPtrdeğeriNULLise,"Memory allocation failed"yazdırın ve programdan çıkın - Tahsis başarılı olduysa,
"Memory allocation successful"yazdırın
- Eğer
- Aşağıdaki giriş değerlerini okuyun ve ok operatörünü kullanarak bunları struct üyelerine atayın:
- Yıl için bir tamsayı okuyun ve
carPtr->yearkullanarak atayın - Marka için bir dize okuyun ve
carPtr->brandkullanarak atayın - Model için bir dize okuyun ve
carPtr->modelkullanarak atayın - Fiyat için bir float okuyun ve
carPtr->pricekullanarak atayın - Kilometre için bir tamsayı okuyun ve
carPtr->mileagekullanarak atayın
- Yıl için bir tamsayı okuyun ve
- Tüm değerleri okuduktan sonra, ok operatörünü kullanarak aşağıdaki hesaplamaları yapın:
- 2024 yılından yılı çıkararak arabanın yaşını hesaplayın:
int age = 2024 - carPtr->year; - Yaşa göre amortisman oranını hesaplayın: eğer yaş 10'dan büyükse amortismanı 0.6 olarak, aksi takdirde 0.8 olarak ayarlayın
- Güncel değeri hesaplayın:
carPtr->price * depreciation
- 2024 yılından yılı çıkararak arabanın yaşını hesaplayın:
- Araba bilgilerini ok operatörünü kullanarak tam olarak şu formatta yazdırın:
"Car Information:""Year: [year]""Brand: [brand]""Model: [model]""Original Price: [price]""Mileage: [mileage]""Age: [age] years""Current Value: [current_value]"
free(carPtr)kullanarak dinamik olarak tahsis edilen belleği serbest bırakın"Memory freed successfully"yazdırın
Bu zorluk; malloc() kullanarak dinamik struct tahsisi, tahsis hatasını kontrol etme, ok operatörünü kullanarak işaretçiler aracılığıyla struct üyelerine erişme ve free() ile tahsis edilen belleği düzgün bir şekilde serbest bırakma konusundaki anlayışınızı test eder. Struct'lar ile dinamik bellek yönetiminin tüm yaşam döngüsünü pratik edeceksiniz.
Kopya kağıdı
Struct'ları yığında (heap) dinamik olarak tahsis etmek için malloc() kullanın:
struct Point *ptr = malloc(sizeof(struct Point));Ok operatörünü kullanarak struct üyelerine işaretçiler aracılığıyla erişin:
ptr->x = 10;
ptr->y = 20;malloc() işleminin başarılı olup olmadığını her zaman kontrol edin ve işiniz bittiğinde belleği serbest bırakın:
if (ptr == NULL) {
// Tahsis hatasını yönetin
}
// Struct'ı kullanın...
free(ptr);Kendin dene
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// YAPILACAK: Car yapısını (struct) burada tanımlayın
int main() {
// YAPILACAK: carPtr adında Car yapısına (struct) bir işaretçi (pointer) bildirin
// YAPILACAK: Bir Car yapısı için bellek ayırmak üzere malloc() kullanın
// YAPILACAK: Bellek tahsisinin başarılı olup olmadığını kontrol edin
// Giriş değerlerini oku
int year, mileage;
char brand[20], model[25];
float price;
scanf("%d", &year);
scanf("%s", brand);
scanf("%s", model);
scanf("%f", &price);
scanf("%d", &mileage);
// YAPILACAK: Ok operatörünü kullanarak giriş değerlerini yapı üyelerine atayın
// YAPILACAK: Yaşı, amortismanı ve mevcut değeri hesaplayın
// YAPILACAK: Araç bilgilerini istenen formatta yazdırın
// YAPILACAK: Ayrılan belleği serbest bırakın ve başarı mesajını yazdırı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ı