C Proqramlaşdırmasında Yaddaş İdarəetmə

giriş

Hər bir proqramlaşdırma dili sistemdəki yaddaşla məşğul olur. Hər bir dəyişənin müəyyən miqdarda yaddaşa ehtiyacı var, proqramın öz proqramını saxlamaq üçün yaddaşa ehtiyacı var, aralıq dəyərləri saxlamaq üçün müvəqqəti yaddaşa ehtiyac var. Bir proqrama və ya dəyişənə təyin edilmiş yaddaş yerləri başqa bir proqram və ya dəyişən tərəfindən istifadə edilməməlidir. He.nce C 2 üsul təqdim edir yaddaşın ayrılması dəyişənlərə və proqramlara. Statik və dinamik yaddaş ayırmaları. Statik olaraq yaddaş bölgüsü, yaddaş tərtib zamanı ayrılır və proqram boyu eyni olacaq. Yaddaşın həcmində və ya yaddaşdakı yerində heç bir dəyişiklik olmayacaq. Amma halda dinamik yaddaş bölgüsü, yaddaş işləmə vaxtı ayrılır və istifadə edilmədikdə ayrılan yaddaş həcmini artıra/azalda və ya yaddaşı tamamilə sərbəst buraxa bilərik. Yaddaşı lazım olduqda yenidən yerləşdirə bilərik. Buna görə dinamik yaddaş bölgüsü yaddaşdan səmərəli istifadə elastikliyi verir.

Davam etmədən əvvəl yaddaş bölgüsü, dəyişənlərin növlərini, yaddaş növlərini və müxtəlif dəyişənlərə və proqramlara yaddaş ayırma üsullarını anlayaq. Bir proqramda fərqli növ dəyişənlərə və yaddaş ehtiyacımız olacaq. Qlobal dəyişənlər, proqram boyunca fərqli funksiyalar və bloklar tərəfindən istifadə ediləcəklərdir. Buna görə də onlara ayrılan yaddaş sahəsi proqram boyunca mövcud olmalıdır. Beləliklə, daimi saxlama sahəsi olaraq bilinən sistemin daxili yaddaşlarına ayrılmış yaddaş alırlar. Eynilə, proqram və onların açıqlamaları da sistem açıldıqda mövcud olmalıdır. Buna görə də daimi saxlama sahəsi tutmalıdırlar.

Yerli dəyişənlər elan olunduqları xüsusi blokda və ya funksiyada mövcud olması lazım olanıdır. Onları daimi saxlama yerində saxlasaq, istifadə olunmayan yaddaşın ayrılmasını saxladığımız üçün yaddaş itkisi olacaq. Beləliklə, yerli dəyişənləri saxlamaq və yığından çıxarmaq üçün yığın yaddaşından istifadə edirik.

Bu yığın yaddaşı ilə yığın yaddaş adlanan daimi yaddaş sahəsi arasında boş bir yaddaş sahəsi var. Bu yaddaş çevik yaddaş sahəsidir və ölçüsünü dəyişməyə davam edir. Beləliklə, proqramın icrası zamanı yaddaşın ayrılması üçün əlverişlidirlər. Yəni dinamik yaddaş ayırmalarında bu yığın yaddaşları istifadə olunur.

Statik yaddaş ayırması

Tutaq ki, iki tam ədədi əlavə edib nəticəni göstərməliyik. Burada hesablamalarda neçə dəyişən və hansı dəyişən növü olduğunu bilirik. yəni; iki ədədi saxlamaq üçün iki tam dəyişənə və nəticəni saxlamaq üçün bir tam dəyişənə ehtiyacımız var. Beləliklə üç tam dəyişənə ehtiyacımız var. Bu, tərtib zamanı özü də 3 tam dəyişən olduğunu bildiyimizi göstərir. Beləliklə, tərtibçinin yaddaşını bu dəyişənlər üçün ayırması asandır. Bu cür qorunan dəyişənlər, proqramın sonuna qədər eyni ölçüdə və yaddaş ünvanında olacaqdır. Bu dəyişənlər üçün ölçü, tip və yaddaş yerində heç bir dəyişiklik olmayacaq.

Dəyişənlər üçün bu tip yaddaş ayırması statik yaddaş ayırması kimi tanınır. Burada dəyişənlərə açıq şəkildə yaddaş ayırmağa ehtiyac yoxdur. Dəyişənləri elan etdiyimiz zaman yaddaş avtomatik olaraq onlara təyin ediləcəkdir. Bu dəyişənlər lokal və ya qlobal dəyişən ola bilər. Ancaq dəyişənin ölçüsünü və növünü əvvəlcədən bilməliyik. Onların sadə dəyişən olmamaları lazımdır; lakin ölçüsünü bildiyimiz təqdirdə onlar sıra və ya quruluş ola bilər.

int intX; // needs to be initialized or assigned some value at run time
int intExample = 0; //normal variable
const int intConstant = 10; // constant, read-only variable

Yuxarıda bütün hallarda tərtibçi əvvəlcədən onların tam ədədlər olduğunu və onların ölçülərini bilir. Beləliklə, kompilyator proqramın özünü icra etmədən əvvəl xüsusi yaddaş yerləri ayıracaqdır. Proqramın icrası bitənə qədər ayrılmış bu xatirələr azad olmayacaq. Bu ayrılmış yaddaş yeri və ölçüləri proqram boyunca sabitdir. Bu tip dəyişənlərin hər hansı biri bu halda əvvəlcədən təyin edilmiş məlumat həcmindən çoxunu saxlaya bilməz.

Dinamik yaddaş ayırması

Bu, statik yaddaş ayırmasından fərqli olaraq. Burada proqram dəyişənin ölçüsünü və hətta bəzən növünü bilmir. Yalnız icra zamanı müəyyən edilir. Bu vəziyyətdə tərtib zamanı heç bir yaddaş təyin edə bilmərik. Yalnız işləmə vaxtında təyin edilə bilər.

Tutaq ki, istifadəçi tərəfindən daxil edilən istənilən sayda əlavə etməliyik. Burada istifadəçi tərəfindən neçə nömrə daxil edildiyindən əmin deyilik. Yalnız onun tam ədədlər daxil etdiyini bilirik. Bu vəziyyətdə dəyişənlərə əvvəlcədən heç bir yaddaş təyin edə bilmərik. Yalnız 2 nömrə və ya 100 nömrə daxil edə bilər. İstifadəçi daha az nömrə daxil edərsə, proqram bu sayda daha az ədədi təyin etmək üçün kifayət qədər çevik olmalıdır və rəqəmlər artdıqca yaddaş ayırma sahəsi də artmalıdır. Ancaq bu, yalnız işləmə müddətində müəyyən edilə bilər - dəyəri daxil edən istifadəçidən asılıdır. Beləliklə, dinamik yaddaş ayırma metodlarından istifadə edilərək işləmə vaxtında yer ayırmaq lazımdır.

İşləmə müddətində dəyişənlərə yaddaş ayırmaq və dəyişənlər üçün yaddaş ölçüsünü dəyişmək üçün müxtəlif funksiyalar mövcuddur. Dinamik yaddaş bölgüsünün ən yaxşı nümunəsi göstəricilər, strukturlar və massivlərdir. Burada dəyişənlərin sayından və istifadə olunan dəyişən növlərindən xəbərdar olmayacağıq. Aşağıdakı funksiyalardan istifadə edərək yaddaş təyin edə və işləmə müddətində dəyişənin növünü təyin edə bilərik.

malloc ()

bu, işləmə zamanı yaddaşın ayrılmasının ən geniş yayılmış metodudur. Bu funksiya tələb olunan yaddaş həcmini iş vaxtında dəyişənlərə ayırır və boşluq göstəricisini ilk yaddaş ünvanına qaytarır. Yəni tələb olunan yaddaş həcmini baytda ayırır və dəyişən üçün məlumat tipini göstərmir / təyin etmir. Dəyişəni boşluq hesab edir və göstəricisini ayrılmış yaddaşdakı ilk bayta aparır. Yaddaş ayıra bilməyəcəyi təqdirdə NULL göstəricisini qaytarır. Yaddaş malloc istifadə edildikdə, dəyişənlər t başlanğıcına qoyulmur

Malloc istifadə edərək yaddaşın ayrılması üçün ümumi sintaksis:

(cast_type *) malloc (ölçü_baytda);
ptr = malloc (10); // 10 bayt yaddaş ayırır

Burada ptr bir göstərici dəyişənidir və 10 bayt yaddaş ayırır. Burada dəyişənin veri tipini təyin etməmişik və ptr indi boş bir göstəricidir. İndi ayrılmış yaddaşdakı ilk bayta işarə edəcəkdir.

Bu göstəricini tam olaraq düzəltməliyiksə, yaddaş ayırarkən növü də göstərməliyik. Bunu etsək, dəyərlər təyin etdikdə, dəyərlər o çox ölçülü aralıqda saxlanacaqdır. Yəni, ptr-i tam olaraq düzəltsək və məlumatları saxlamağa başlasaq, hər bir məlumat dəyəri 4 bayt aralığında saxlanacaqdır.

ptr = (int*)malloc(10); //returns integer pointer to ptr pointing to first byte of allocated memory

Bu, ptr-ı tam göstərici kimi edəcək və ayrılmış yaddaş yalnız 10 baytdır. Tam dəyər üçün bölünsə (hər biri 4 bayt), onda yalnız 2 dəyər saxlaya biləcəyik. Ancaq tam ədədin ölçüsü sistemdən sistemə dəyişə bilər. Beləliklə, prosessorun özünə tam ədədin ölçüsünü təyin etməsinə və göstəriciyə yaddaş ayırmasına icazə verə bilərik. Bundan əlavə, tam ölçülü neçə məlumat dəyərinin saxlanılması lazım olduğunu təyin edə bilərik.
ptr = (int*)malloc(10* sizeof(int)); //allocates memory sufficient for 10 integer values and returns integer pointer to ptr

Malloc içindəki parametr ayrılacaq yaddaşın ümumi ölçüsünə sahib olacaqdır. Ancaq ümumi ölçüsü həmişə hesablaya bilmərik. Beləliklə, ayrılacaq yaddaşın ümumi ölçüsünü təyin etmək üçün malloc ilə hesablama aparırıq.

Tutaq ki, 100 elementi saxlamaq üçün dinamik bir üzən rəqəmlər seriyası yaratmalıyıq. Sonra:

arr = (float*)malloc(10 * sizeof(float));

Eyni üsul, strukturlar üçün yaddaş ayırmaq üçün istifadə edilə bilər. Tutaq ki, tələbə quruluşumuz var. Sonra:
struct student *std = (struct student *)malloc(sizeof(struct student));

Burada quruluş göstəricisi * std yaddaşa dinamik olaraq ayrılır. Bir tələbə detalını saxlamaq üçün ayrılmış yaddaşı alır və göstəricini tələbə quruluşunun ilk üzvünə yönəltməyə imkan verir. Fərz edək ki, eyni * std-də birdən çox tələbə olmalıdır - deyin 50 tələbə. Sonra 50 * sizeof (tələbə) tutmaq üçün yaddaş ayırmaq lazımdır.
struct student *std = (struct student *)malloc(50 * sizeof(struct student));

calloc ()

Bu funksiya malloc-a bənzəyir. Ancaq bu funksiya ümumiyyətlə massivlərə və strukturlara xatirələr ayırmaq üçün istifadə olunur. Yaddaş ayırmaq üçün calloc () istifadə edildikdə, dəyişəni avtomatik olaraq sıfıra keçirir. Tutaq ki, 50 şagird üçün yaddaş ayırmalıyıq. Malloc-da ümumi yaddaş ölçüsünü əldə etmək üçün tələbə quruluşunun ölçüsü ilə 50-yə vururuq. Ancaq calloc-da, tələbənin 50 və ölçüsünü aşağıda göstərildiyi kimi iki arqument kimi keçiririk. Bunun xaricində, malloc ilə eyni şəkildə yaddaş ayırır.

(cast_type *) calloc (blocks , size_of_block);
struct student *std = (struct student *)calloc(sizeof(struct student));// single student
struct student *std = (struct student *)malloc(50, sizeof(struct student));// 50 students

realloc ()

Fərz edək ki, artıq ayrılmış dəyişənin yaddaş ölçüsünü artırmaq və ya azaltmaq lazımdır. Bu vəziyyətdə dəyişənin yaddaş ölçüsünü yenidən təyin etmək üçün realloc funksiyasından istifadə edə bilərik.

(cast_type *) realloc (bloklar, size_of_block);
Yeni blok ölçüsü ilə tamamilə yeni yaddaş yeri ayıracaqdır.

pulsuz ()

Ayrılmış yaddaşı artıq lazım olmadıqda buraxmaq həmişə yaxşı bir tətbiqdir. Bunun səbəbi, hər dəfə yaddaş ayrılır dinamik olaraq, dəyişənlərə çoxlu yaddaş sahəsi sərf edəcəklər. Yalnız buraxıldıqda eyni və ya fərqli proqramlar üçün əlçatan olacaq. Bununla birlikdə, proqram tamamlandıqdan sonra proqramın bütün xatirələri avtomatik olaraq yayımlanacaq.

pulsuz (dəyişən_adı);
pulsuz (std);

xülasə

Translate »
1