C xotira ajratish
Xotirani band qilish jarayoni xotira ajratish (allocation) deb ataladi. Xotira ajratish usuli xotira turiga bog‘liq.
C tilida xotiraning ikki turi mavjud: statik xotira va dinamik xotira.
Statik xotira
Statik xotira — dastur ishga tushishidan oldin o‘zgaruvchilar uchun band qilinadigan xotira. Statik xotira ajratish kompilyatsiya vaqtida xotira ajratish deb ham ataladi.
Dastur kompilyatsiya qilinganda C tili har bir o‘zgaruvchi uchun avtomatik ravishda xotira ajratadi.
Masalan, 20 nafar talaba uchun (masalan, yozgi semestr uchun) butun sonlar massivini yaratsangiz, C tili 20 ta element uchun joy band qiladi — bu odatda 80 bayt xotira (20 * 4):
Lekin semestr boshlanganda faqat 12 nafar talaba qatnashayotgani ma’lum bo‘ladi. Demak, siz 8 ta foydalanilmagan element joyini behuda sarfladingiz.
Massiv o‘lchamini o‘zgartira olmaganingiz uchun keraksiz band qilingan xotira qolib ketadi.
E’tibor bering, dastur baribir ishlaydi va hech qanday zarar ko‘rmaydi. Lekin dasturingizda bunday kod ko‘p bo‘lsa, u optimal holatdagidan sekinroq ishlashi mumkin.
Ajratilgan xotirani yaxshiroq nazorat qilmoqchi bo‘lsangiz, quyidagi "Dinamik xotira" bo‘limiga qarang.
Dinamik xotira
Dinamik xotira — dastur ishga tushganidan keyin ajratiladigan xotira. Dinamik xotira ajratish bajarilish vaqtida (runtime) xotira ajratish deb ham ataladi.
Statik xotiradan farqli o‘laroq, istalgan vaqtda qancha xotira ishlatilayotganini to‘liq nazorat qilasiz. Qancha xotira kerakligini aniqlaydigan va uni ajratadigan kod yozishingiz mumkin.
Dinamik xotira biror o‘zgaruvchiga tegishli emas, unga faqat ko‘rsatkichlar orqali murojaat qilish mumkin.
Dinamik xotira ajratish uchun malloc() yoki calloc() funksiyalaridan foydalanishingiz mumkin. Ulardan foydalanish uchun <stdlib.h> sarlavha faylini qo‘shish zarur. malloc() va calloc() funksiyalari ma’lum hajmdagi xotirani ajratadi va uning manziliga ko‘rsatkich qaytaradi.
int *ptr1 = malloc(size);
int *ptr2 = calloc(amount, size);
malloc() funksiyasining bitta parametri bor — size; u qancha xotira ajratilishini baytlarda belgilaydi.
calloc() funksiyasining ikkita parametri bor:
- amount - ajratiladigan elementlar sonini belgilaydi
- size - har bir elementning baytlarda o‘lchangan hajmini belgilaydi
Eslatma: malloc() ajratgan xotiradagi ma’lumotlarni oldindan aytib bo‘lmaydi. Kutilmagan qiymatlarga duch kelmaslik uchun xotiradan o‘qishdan oldin unga biror narsa yozib qo‘ying.
malloc() funksiyasidan farqli o‘laroq, calloc() funksiyasi ajratilgan xotiraning hammasiga nol yozadi. Biroq bu calloc() funksiyasini biroz kamroq samarali qiladi.
Ma’lumot tipi uchun kerakli miqdorda xotira ajratishning eng yaxshi usuli — sizeof operatoridan foydalanish:
int *ptr1, *ptr2;
ptr1 = malloc(sizeof(*ptr1));
ptr2 = calloc(1, sizeof(*ptr2));
Ehtiyot bo‘ling: sizeof(*ptr1) yozuvi manzildagi ma’lumotning o‘lchamini o‘lchash kerakligini bildiradi. Agar * belgisini unutib, o‘rniga sizeof(ptr1) deb yozsangiz, u ko‘rsatkichning o‘zini — xotira manzilini saqlash uchun kerak bo‘ladigan (odatda) 8 baytni o‘lchaydi.
Eslatma: sizeof operatori qancha dinamik xotira ajratilganini o‘lchay olmaydi. Dinamik xotirani o‘lchaganda u faqat xotiraning ma’lumot tipi o‘lchamini ko‘rsatadi. Masalan, 5 ta float qiymat uchun joy band qilsangiz, sizeof operatori 4 ni qaytaradi — bu bitta float qiymat uchun kerak bo‘ladigan baytlar soni.
Keling, yuqoridagi talabalar misolini dinamik xotira yordamida yaxshilaymiz.
Avval aytib o‘tilganidek, qancha xotira ajratilganini o‘lchash uchun sizeof operatoridan foydalana olmaymiz — buni elementlar sonini ma’lumot tipining o‘lchamiga ko‘paytirib hisoblashimiz kerak:
Misol
int *students;
int numStudents = 12;
students = calloc(numStudents, sizeof(*students));
printf("%d", numStudents * sizeof(*students)); // 48 bytes
O‘zingiz sinab ko‘ring »
Eslatmalar
Dinamik xotira ajratish bilan ishlaganda xatolarni tekshirishingiz va dastur oxirida xotirani bo‘shatishingiz ham kerak. Bu haqda keyingi boblarda batafsil bilib olasiz.
Stek xotirasi
To‘liqlik uchun stek xotirasini ham aytib o‘tish joiz. Stek xotirasi — funksiyalar ichida e’lon qilingan o‘zgaruvchilar uchun band qilinadigan dinamik xotira turi. Funksiya ichida e’lon qilingan o‘zgaruvchilar statik xotiradan emas, stek xotirasidan foydalanadi.
Funksiya chaqirilganda uning o‘zgaruvchilari uchun stek xotirasi ajratiladi. Funksiya ishini tugatgach, stek xotirasi bo‘shatiladi.
Ichma-ich funksiya chaqiruvlari va rekursiyaning xotiradan foydalanishini nazorat qila olish uchun stek xotirasidan xabardor bo‘lish foydali. Haddan tashqari ko‘p takrorlanadigan rekursiya juda ko‘p stek xotirasini egallashi mumkin. Bu holat stek to‘lib ketishi (stack overflow) deb ataladi.
W3Schools Pathfinder
Yutuqlaringizni kuzating – bu bepul!
