Mavzu: Dinamik hotira yaratish va undan foydalanish Reja: I. Kirish II. Asosiy qism


Download 120 Kb.
bet7/8
Sana19.04.2023
Hajmi120 Kb.
#1362707
1   2   3   4   5   6   7   8
Bog'liq
Dinamik hotira yaratish va undan foydalanish

manzil

xotira tarkibi




dastur kodi va ma'lumotlari,
o'zgarishlardan himoyalangan

...

statik o'zgaruvchilar
dasturlari




dinamik xotira

maks. manzil (2 32 -4)

stack

Dinamik xotira strukturasi avtomatik ravishda C yoki C++ ish vaqti tizimi tomonidan saqlanadi. Yig'ma olingan va bo'sh segmentlardan iborat bo'lib, ularning har birida segment deskriptori mavjud. Xotirani tortib olish so'rovini bajarayotganda, ijro etuvchi tizim etarli o'lchamdagi bo'sh segmentni qidiradi va unda kerakli uzunlikdagi segmentni ushlaydi. Xotira segmenti chiqarilganda, u bepul deb belgilanadi, agar kerak bo'lsa, bir nechta ketma-ket bo'sh segmentlar birlashtiriladi.
Si tili dinamik xotirani olish va ajratish uchun standart malloc va bepul funksiyalardan foydalanadi; ularning prototiplari standart sarlavha fayli "stdlib.h"da tasvirlangan. (Malloc nomi qisqartmasi xotira ajratish- "xotirani ushlash".) Ushbu funktsiyalarning prototiplari quyidagicha ko'rinadi:
void *malloc (size_t n); // Xotiraning bir qismini oling // o'lchamdagi n bayt void free(void *p); // Xotira maydonini // p manzili bilan bo'shating
Bu erda n - baytlarda olingan maydonning o'lchami, size_t - aniqlovchi butun son turlaridan birining nomi. maksimal hajmi qo'lga kiritilgan hudud. Size_t turi "stdlib.h" standart sarlavha faylida typedef bayonoti yordamida ko'rsatilgan (117-betga qarang). Bu C dasturining matni ishlatiladigan arxitekturadan mustaqil bo'lishini ta'minlaydi. 32-bitli arxitekturada size_t belgisiz butun son sifatida aniqlanadi:
typedef unsigned int size_t;
Malloc funksiyasi olingan xotira maydonining manzilini qaytaradi yoki ishlamay qolganda nolga teng (etarlicha katta bo'sh maydon bo'lmasa). Erkin funksiya berilgan manzilda xotiraning bir qismini chiqaradi. Manzilni o'rnatish uchun ko'rsatgich ishlatiladi. umumiy turi bekor*. Malloc funktsiyasini chaqirgandan so'ng, uni quyma operatsiyadan foydalanib, beton turiga ko'rsatgichga tashlash kerak, 3.4.11-bo'limga qarang. Misol uchun, quyidagi misol 4000 baytlik to'pni oladi va uning manzilini 1000 butun sonli massivga ko'rsatgichga belgilaydi:
int*a; // Butun sonlar massiviga ko'rsatgich. . . a = (int *) malloc (1000 * sizeof(int));
Malloc funktsiyasi argumentidagi ifoda 4000 ga teng, chunki sizeof(int) butun sonining o'lchami to'rt baytni tashkil qiladi. Ko'rsatkichni aylantirish uchun umumiy turdagi ko'rsatgichdan ko'rsatgichni butun songa o'tkazish (int *) operatsiyasidan foydalaning.
Misol: birinchi n tub sonni chop etish
Keling, dinamik xotirani saqlashdan foydalanadigan misolni ko'rib chiqaylik. n butun sonini kiritishingiz va birinchi n tub sonni chop etishingiz kerak. (Tod son - bu arzimas bo'luvchilarga ega bo'lmagan son.) Biz quyidagi algoritmdan foydalanamiz: uchtadan boshlab barcha toq sonlarni ketma-ket tekshiramiz (ikkitasini alohida ko'rib chiqamiz). Keyingi raqamni algoritmning oldingi bosqichlarida topilgan va tekshirilayotgan raqamning kvadrat ildizidan oshmaydigan barcha tub sonlarga ajratamiz. Agar bu tub sonlarning birortasiga bo'linmasa, u holda uning o'zi tub sondir; u chop etiladi va topilgan tub sonlar qatoriga qo'shiladi.
Kerakli n tub sonlar soni dastur boshlanishidan oldin ma'lum bo'lmagani uchun ularni statik xotirada saqlash uchun massiv yaratish mumkin emas. Chiqish yo'li n raqamini kiritgandan so'ng dinamik xotirada massiv uchun joy egallashdir. Mana dasturning toʻliq matni:
#o'z ichiga oladi #o'z ichiga oladi #o'z ichiga oladi int main() ( int n; // Kerakli tub sonlar soni int k; // Topilgan tub sonlarning joriy soni int *a; // Topilgan tub sonlar massiviga ko‘rsatgich int p; // int r ni tekshirish uchun keyingi raqam; // p int i ning butun kvadrat ildizi; // Bosh bo‘luvchining indeksi bool prime; // Prime prime printf("Tub sonlar sonini kiriting: "); scanf("%d", &n); if (n)<= 0) // Некорректное значение =>qaytish 1; // xato kodi bilan chiqish // Bosh sonlar massivi uchun xotirani yozib olish a = (int *) malloc(n * sizeof(int)); a = 2; k = 1; // Massivga 2 qo'shing printf("%d ", a); // va uni chop eting p = 3; esa (k< n) { // Проверяем число p на простоту r = (int)(// Целая часть корня sqrt((double) p) + 0.001); i = 0; prime = true; while (i < k && a[i] <= r) { if (p % a[i] == 0) { // p делится на a[i] prime = false; // =>p asosiy emas, tanaffus; // tsikldan chiqish ) ++i; // Keyingi tub bo'luvchiga ) if (tut) ( // Agar tub sonni topsangiz, a[k] = p; // keyin uni ++k massiviga qo'shing; // tub sonlar sonini ko'paytirish printf( "%d ", p ); // tub sonni chop eting, agar (k % 5 == 0) ( // O'tish yangi qator printf("\n"); // har beshta raqamdan keyin ) ) p += 2; // Keyingi toq raqamga ) if (k % 5 != 0) ( printf("\n"); // Tarjima satri ) // Bo'sh dinamik xotira (a); qaytish 0; )
Ushbu dastur qanday ishlashiga misol:
Oddiy: 50 29 299 181 191 103 193 193 97 83 83 103 108 103 108 83 83 97 193 197 197 197 197 197 197 197 197 197 197 197 197 197 197 199 211 223 227 229
C++ yangi va o'chirish operatorlari
C++ tili dinamik xotirani olish va ajratish uchun new va delete operatorlaridan foydalanadi. C standart kutubxonasining bir qismi bo'lgan malloc va bepul funktsiyalardan farqli o'laroq, ular C ++ tilining bir qismidir.
T ba'zi C yoki C++ tipidagi bo'lsin, p T tipidagi ob'ektga ko'rsatgich bo'lsin. Keyin T tipidagi bitta element o'lchamli xotirani olish uchun yangi operator ishlatiladi:
T*p; p = yangi T;
Misol uchun, sakkiz baytni ushlab turish uchun haqiqiy raqam fragment double tipida ishlatiladi
juft *p; p = yangi dubl;
new dan foydalanganda, malloc dan farqli o'laroq, ko'rsatgichni void* dan kerakli turga o'tkazish shart emas: new operator ko'rsatgichni new so'zidan keyin yozilgan turga qaytaradi. C va C++ tillarida ikkita ekvivalent parchalarni solishtiring.
global o'zgaruvchilar va konstantalarni saqlaydi;
hajmi kompilyatsiya vaqtida aniqlanadi.
stack
mahalliy o'zgaruvchilarni, funktsiya argumentlarini va hisob-kitoblarning oraliq qiymatlarini saqlaydi;
hajmi dastur ishga tushirilganda aniqlanadi (odatda 4 MB ajratiladi).
Uyum
dinamik ravishda ajratilgan xotira;
OT xotirani qismlarga ajratadi (kerak bo'lganda).
Misol:// 1000 int element uchun xotira ajratish
int * p = (int *) malloc (1000*sizeof(int));
agar (p==NULL) chiqadi<< "\n память не выделена";
bepul (p); // xotirani uyaga qaytarish
2. Ajratish (xotirani ushlash): void *calloc(size_t nmemb, size_t size);
Funktsiya malloc ga o'xshash ishlaydi, lekin sintaksisda farqlanadi (ajratilgan xotira hajmi o'rniga elementlar soni va bitta element hajmini ko'rsatish kerak) va bunda ajratilgan xotira nolga qaytariladi. Misol uchun, int * p = (int *) calloc(1000, sizeof(int)) bajarilgandan so'ng p nolga ishga tushirilgan 1000 ta elementdan iborat int massivining boshiga ishora qiladi.
3. Xotira hajmini o'zgartirish: void *realloc(void *ptr, size_t size);
Funktsiya ajratilgan xotira hajmini o'zgartiradi ( ptr, chaqiruvdan olingan malloc, calloc yoki realloc). Agar parametrda ko'rsatilgan o'lcham bo'lsa hajmi ko'rsatgich ostida ajratilganidan kattaroq ptr, keyin yo'qolgan xotira katakchalarini allaqachon ajratilganlar bilan bir qatorga ajratish mumkinmi yoki yo'qligi tekshiriladi. Agar etarli joy bo'lmasa, u holda o'lcham bilan yangi xotira qismi ajratiladi hajmi va ko'rsatkich ma'lumotlari ptr yangi bo'limning boshiga ko'chiriladi.
Dasturni bajarish jarayonida dinamik xotira bo'limi ushbu bo'limga murojaat qiluvchi ko'rsatgich mavjud bo'lgan joyda mavjud bo'ladi. Shunday qilib, qaysidir blokda (masalan, asosiy bo'lmagan funktsiya tanasida) ajratilgan dinamik xotira bilan ishlashning quyidagi uchta varianti mumkin.
Ko'rsatkich (dinamik xotira maydoniga) mahalliy avtomatik xotira ob'ekti sifatida aniqlanadi. Bunday holda, ajratilgan xotira ko'rsatgichni lokalizatsiya blokidan chiqishda mavjud bo'lmaydi va blokdan chiqishdan oldin bo'shatish kerak.
( int* p= (int *) calloc(n, sizeof(int))
bepul (p); // bepul dyn. xotira
Ko'rsatkich mahalliy statik saqlash ob'ekti sifatida aniqlanadi. Blokda bir marta ajratilgan dinamik xotira har safar blok qayta kiritilganda ko'rsatgich orqali mavjud bo'ladi. Xotira faqat foydalanilmayotganda bo'shatiladi.
(statik int* p = (int *) calloc(n, sizeof(int));
p= (int *) calloc(n, sizeof(int));
f(50); //dinni ajratib ko'rsatish. bo'shatish uchun xotira
f1(100); //dinni ajratib ko'rsatish. xotira (birinchi kirish)
f1(100); // din bilan ishlash. xotira
f1(0); // bepul dyn. xotira
Ko'rsatkich blokga nisbatan global ob'ektdir. Ko'rsatkich "ko'rinadigan" barcha bloklarda dinamik xotira mavjud. Xotira faqat foydalanilmay qolganda bo'shatiladi.
int*pG; //din uchun ish ko'rsatgich. xotira (global o'zgaruvchi)
void init (int hajmi)
uchun (i=0; i< size; i++) //цикл ввода чисел
( printf("x[%d]=",i);
scanf("%d", &pG[i]);
int summasi (int hajmi)
uchun (i=0; i< size; i++) //цикл суммирования
// xotirani ajratish
pG= (int *) calloc(n, sizeof(int));
// dinamik xotira bilan ishlash
printf(\ns=%d\n",sum(n));
bepul (pG); pG=NULL; // xotirani ajratish

Download 120 Kb.

Do'stlaringiz bilan baham:
1   2   3   4   5   6   7   8




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling