- Yığıt (stack) ile dinamik bellek (heap) arasındaki farkı açıklamak
mallocvecallocile bellek ayırmak, sonucuNULLiçin denetlemek vefreeile geri vermek- Bellek sızıntılarını ve serbest bırakılmış belleği kullanma hatalarını tanımak
structvetypedefile kendi türünü oluşturmak ve alanlara.ve->ile erişmek
Bir okul için elektronik not defteri yazıyorsun. Bir sınıfta kaç öğrenci olacak: 12, 25 mi, yoksa 40 mı? Programı yazarken bunu bilemezsin ama bir dizinin boyutu önceden belli olmalıdır. Üstelik her öğrenci için ad, yaş ve not ortalaması gibi birkaç bilgi saklaman gerekir. Bu derste iki sorunu da çözeceğiz: program çalışırken tam gerektiği kadar belleği dinamik olarak ayıracak ve ilişkili verileri yapılarda (struct) toplayacağız.
Yığıt ve yığın
Bir fonksiyonun yerel değişkenleri yığıtta (stack) yaşar: fonksiyon başlarken oluşur, bitince kendiliğinden silinir. Yığıt hızlıdır ama küçüktür ve boyutların derleme sırasında bilinmesi gerekir. Dinamik bellek (yığın, İngilizcesiyle heap) ise büyük bir depodur: ondan istediğin an istediğin boyutta yer isteyebilirsin. Ama bir şartla: işin bitince o yeri kendin geri vermelisin. Gereken tüm fonksiyonlar stdlib.h başlığındadır.
| Fonksiyon | Ne yapar |
|---|---|
malloc(size) | size baytlık bir blok ayırır; içeriği rastgeledir |
calloc(n, size) | her biri size bayt olan n eleman için yer ayırır ve hepsini sıfırla doldurur |
realloc(p, size) | önceden ayrılmış bir bloğu büyütür veya küçültür |
free(p) | bloğu sisteme geri verir |
malloc, calloc ve realloc NULL döndürür.#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 5;
int *squares = malloc(n * sizeof(int));
if (squares == NULL) {
printf("Not enough memory\n");
return 1;
}
for (int i = 0; i < n; i++) {
squares[i] = (i + 1) * (i + 1);
}
for (int i = 0; i < n; i++) {
printf("%d%s", squares[i], i < n - 1 ? ", " : "\n");
}
free(squares);
squares = NULL;
return 0;
}1, 4, 9, 16, 25
n sabittir ama kullanıcının girdiği bir sayı da olabilirdi. Ayrılan blokla sıradan bir dizi gibi çalışıyoruz.calloc belleği sıfırlarla doldurduğu için sayaçlarda kullanışlıdır. Aşağıdaki program bir oylamada her seçeneğin kaç oy aldığını sayar:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int votes[] = {2, 0, 1, 2, 2, 1};
int n = 6, options = 3;
int *counts = calloc(options, sizeof(int));
if (counts == NULL) {
return 1;
}
for (int i = 0; i < n; i++) {
counts[votes[i]]++;
}
for (int i = 0; i < options; i++) {
printf("Option %d: %d\n", i, counts[i]);
}
free(counts);
return 0;
}Option 0: 1 Option 1: 2 Option 2: 3
for (int i = 0; i < 1000; i++) {
int *tmp = malloc(1000 * sizeof *tmp);
if (tmp == NULL) {
break;
}
tmp[0] = i;
}free(tmp) yok; toplamda yaklaşık 4 milyon bayt sızıyor.Yapılar (struct)
Farklı türlerdeki birkaç alanı tek bir ad altında toplayan, kullanıcının tanımladığı tür. Örneğin bir öğrenci yapısında ad (char dizisi), yaş (int) ve not ortalaması (double) olabilir.
#include <stdio.h>
#include <string.h>
struct Student {
char name[20];
int age;
double average;
};
int main(void) {
struct Student s1;
strcpy(s1.name, "Aysel");
s1.age = 15;
s1.average = 4.75;
struct Student s2 = {"Murad", 16, 4.2};
printf("%s, %d, %.2f\n", s1.name, s1.age, s1.average);
printf("%s, %d, %.2f\n", s2.name, s2.age, s2.average);
return 0;
}Aysel, 15, 4.75 Murad, 16, 4.20
s1.age. Bir yapıya, alanlarının sırasıyla süslü parantez içinde ilk değer verilebilir.Her seferinde struct Student yazmamak için typedef ile türe kısa bir ad verilir. Bir yapıya işaretçi olduğunda alana -> operatörüyle erişilir: p->age, (*p).age demektir. Bir yapıyı fonksiyona işaretçiyle aktarmak hem onu değiştirmeye olanak tanır hem de tüm yapıyı kopyalamaktan daha ucuzdur.
#include <stdio.h>
typedef struct {
char name[20];
int age;
double average;
} Student;
void birthday(Student *s) {
s->age++;
}
void print_student(const Student *s) {
printf("%s, %d, %.2f\n", s->name, s->age, s->average);
}
int main(void) {
Student group[3] = {
{"Aysel", 15, 4.75},
{"Murad", 16, 4.2},
{"Leyla", 15, 4.5}
};
birthday(&group[1]);
for (int i = 0; i < 3; i++) {
print_student(&group[i]);
}
return 0;
}Aysel, 15, 4.75 Murad, 17, 4.20 Leyla, 15, 4.50
birthday, Murad'ın yaşını 16'dan 17'ye çıkardı.Önemli noktalar
- Yerel değişkenler yığıtta kendiliğinden oluşur ve silinir; dinamik bellek ise
free'ye kadar yaşar. mallocrastgele içerikli,callocise sıfırlanmış bellek ayırır; ikisinin sonucunu daNULLiçin denetle.- Her
mallociçin birfree; yoksa bellek sızar. structfarklı türlerdeki alanları bir araya getirir,typedefbir türe kısa ad verir.- Değişkende alana
.ile, işaretçide->ile erişilir:p->age=(*p).age.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
malloc ne döndürür?