C Programming chapter 11
Transcript of C Programming chapter 11
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
11פרק
הקצאה זיכרון דינאמית
Dynamic Memory Allocation
בילור שייקה "ד
יועץ ומרצה בכיר למדעי המחשב וטכנולוגית מידע
ומנהליותאקדמיות , למערכות מידע חינוכיותמומחה
Cקורס יסודות התכנות בשפת
1
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
:היוםנושאי השיעור
תזכורת :
.מבנים ורקורסיה
הקצאת זיכרון דינאמית.
הקצאת זיכרון דינאמית2
הגדרת מבנה חדש -מבנים -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
ידי שתי קואורדינטות-נקודה במישור מיוצגת על ,X ו- Y .
הגדרת מבנה שייצג נקודה תיראה למשל כך:
typedef struct point
{
double x;
double y;
}point;
כ "בד)אלא בתחילת הקובץ , ההגדרה הזו לא תופיע בתוך פונקציה
(.define# -וה include# -אחרי שורות ה מייד
כפי שנבחן בהמשך, כעת ניתן להגדיר בתוכנית משתנים מהסוג הזה .
3
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
ממנו/לקרוא אליו/ניתן לגשת לכל אחד מהשדות של מבנה ולכתוב .
למשל:
int main()
{
struct point P1,P2;
P1.x = 6;
P1.y = 7;
P2.x = 4;
P2.y = 2;
printf(“%.2lf\n”, P1.y);
return 0;
}
P1 P2
4
7 2
6 x
y
x
y
(7יודפס )
הגדרת מבנה חדש -מבנים -חזרה 4
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
#include <stdio.h> struct point { double x; double y; }; int main() { struct point P1,P2; P1.x = 6; P1.y = 7; P2.x = 4; P2.y = 2; printf(“%.2lf\n”, P1.y); return 0; }
P1 P2
4
7 2
6 x
y
x
y
הגדרת מבנה חדש -מבנים -חזרה 5
כתיבה מקוצרת –מבנים -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
שמו של הטיפוס החדש שהגדרנו הואstruct point
אפשר לחסוך את כתיבת המילהstruct באמצעות הפקודה
typedef ,משתנה-שמאפשרת לתת שם חדש לטיפוס :
struct point
{
double x;
double y;
};
typedef struct point point_t;
טיפוס קיים שם חדש
6
typedefעוד על -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
struct complex
{
double real;
double image;
};
int main()
{
struct complex c={5,7};
struct complex *pc;
}
struct complex
{
double real;
double image;
};
typedef struct complex
complex_t;
int main()
{
complex_t c={5,7};
complex_t *pc;
}
7
מצביעים ומבנים -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
כדי להגיע לשדות של , בדוגמא זוP דרךptr שמצביע
:כרגיל* -אפשר להשתמש ב, Pעל
(*ptr).x = 3; שקול ל- P.x = 3;
(*ptr).y = 7; שקול ל- P.y = 7;
כי אחרת לנקודה יש קדימות על פני יש צורך בסוגריים
*. -ה
8
גישה לשדות המבנה –מצביעים ומבנים -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
כדי להגיע לשדות של , בדוגמא זוP דרךptr שמצביע עלP ,
:כרגיל* -אפשר להשתמש ב
(*ptr).x = 5; שקול ל- P.x = 5;
(*ptr).y = 8; שקול ל- P.y = 8;
חץ : כלל נשתמש לצורך זה בסימון מקוצר-אבל בדרך<-
ptr->x = 5; שקול ל- P.x = 5;
ptr->y = 8; שקול ל- P.y = 8;
כלומר משמעות החץ היא גישה לשדה במבנה שמצביעים עליו.
9
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
struct complex
{
double real;
double image;
};
int main()
{
struct complex c;
struct complex *pc;
c.real = 5;
c.image = 7;
}
5
7 c.image:
c.real:
c
שימוש במצביעים - Syntax מבנים -חזרה 10
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
5
7 c.image:
c.real:
c struct complex {
double real, image;
};
int main()
{
struct complex c;
struct complex *pc;
c.real = 5;
c.image = 7;
pc = &c;
pc->real = 3; pc->image = 4;
}
pc
3
4 pc.image:
pc.real:
pc
כתובות ומצביעים - Syntax מבנים -חזרה 11
0x7fff9255c05c
0x7fff9255c05c
0x7fff9255c05c
מבנה בתוך מבנה -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
הקודקודיםידי הקואורדינטות של שני -אפשר להגדיר את זה על: struct rect { double xl, xh, yl, yh; };
נקודות 2י "עברור יותר להגדיר. כאן גם את הרישום המקוצר עם נדגיםtypedef:
struct rect { point_t p; point_t q; }; typedef struct rect rect_t;
12
כתיבה מקוצרת –מבנים -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
שמו של הטיפוס החדש שהגדרנו היהstruct point
אפשר לחסוך את כתיבת המילהstruct באמצעות הפקודה
typedef ,משתנה-שמאפשרת לתת שם חדש לטיפוס :
struct point
{
double x;
double y;
};
typedef struct point point_t;
טיפוס קיים שם חדש
13
מערך של מבנים -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
אפשר להגדיר מערך של מבנים, כמו טיפוסי משתנים אחרים.
מערך זה יוגדר ויכיל בתוכו שדות שהם מבנים הכוללים תתי
.שדות
אפשר להגדיר מערך של נקודות, למשל:
int main()
{
point_t arr[20];
…
…
return 0;
}
14
מערך של מלבנים בזיכרון -חזרה
rect_t
rect_t
rect_t
rect_t
rect_t
rect_t
rect_t
point_t p
point_t q
double x
double y
double x
double y
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
כל מלבן מכיל שני
שדות מסוג נקודה
כל נקודה מכילה שני
doubleשדות מסוג
המלבנים נשמרים ברצף בזיכרון
15
ומבניםמערכים -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
לסוגים שכמו מאחר ומבנים מגדירים סוג חדש של משתנים הרי • .סוגי משתנים אלהליצור מערכים עבור נשאף רגילים
5
7
2
1
7
2
1
8
complex_t arr[SIZE]=
{{5,7},{2,1},{7,2},{1,8}}
arr[1].image = 9;
arr[1].real = 2;
arr[3].image = 8;
arr[3].real = 3;
image: array
real:
image:
real:
image:
real:
image:
real:
0
1
2
3
16
מערכים ומבנים אחרי ביצוע הפקודות -חזרה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
5
7
9
2
7
2
8
3
image:
array
real:
image:
real:
image:
real:
image:
real:
0
1
2
3
complex_t arr[SIZE]= {{5,7},{2,1},{7,2},{1,8}}
arr[1].image = 9;
arr[1].real = 2;
arr[3].image = 8;
arr[3].real = 3;
17
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
אותה כשכתבנו בתוכנית לנו יהיו משתנים איזה הגדרנו עכשיו עד .משתנים של "סטטית הקצאה" מוגדר זה ,הפתרון תכנון פי על
טיפוס את בענוק ,מערך בהגדרת במיוחד שכיחה הייתה ההגדרה אם) הריצה בזמן אותו לשנות יכולנו ולא ,גודלו את ,הנתונים
.(עליון חסם שיש הנחנו מראש ידוע היה לא הגודל
למשל:
int main()
{
int arr[10];
}
להגדיל נוכל ולא ,בזיכרון תאים עשרה יוקצו הזה המערך עבור .(int) בתים ארבעה יכלול תא כל ,התוכנית הרצת כדי תוך אותו
הקצאת זיכרון דינאמית20
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
הזה המערך עבור, arr[10], בזיכרון תאים עשרה יוקצו, תא כל ,התוכנית הרצת כדי תוך אותו להגדיל נוכל ולא
.int הנתונים טיפוס בגלל בתים ארבעה יכלול
הריצה בזמן נוספים משתנים להגדיר נבחר לפעמים, .הפתרון תכנון במהלך המתעורר מצורך כתוצאה
שתלוי בגודל מערך הגדרת בעת בפרט נפוצה התופעה את מראש נדע ולא יתכן כזה במערך ,מהמשתמש בקלט .המערך גודל על עליון-החסם של ערכו
הקצאת זיכרון דינאמית21
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
ב זאת לממש אפשר- C בשם בפונקציה שימוש י"ע:
malloc(), כדי תוך בזיכרון מקום מקצה זו פונקציה
הוא ולכן בקלט תלוי להיות יכול הגודל) התוכנית ריצת .(דינאמי
הפונקציה malloc() בספריה נמצאת stdlib.h.
(בבתים) המבוקש הזיכרון גודל את לפונקציה מעבירים, .בזיכרון שהוקצה הזה בגודל לאזור מצביע מחזירה והיא
דינאמית הקצאה" נקראת הריצה בזמן זיכרון הקצאת".
צורך -הקצאת זיכרון דינאמית 22
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int main() { int *arr=NULL, size;
printf("Enter array size\n");
scanf("%d", &size);
arr = (int * ) malloc (size* sizeof(int) ) ;
}
מסוג משתנים 10 בגודל רצוף מקום בזיכרון תקצה :היא המשמעות int, ל כמצביע ,שהוקצה המקום של ההתחלה כתובת את ותחזיר- int המשתנה אל arr.
התוכנית ריצת בזמן מתבצעת ההקצאה. הפונקציה sizeof טיפוס או משתנה של בבתים גודל מחזירה
.(סיביות 320 שהם בתים 40 כלל-בדרך דורשים יםint 10) משתנה
syntax -הקצאת זיכרון דינאמית 23
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
)= מצביע המצביע סוג ) malloc ( תאים 'מס * תא גודל );
:למשל
arr = (int * ) malloc (size * sizeof(int) );
ה- casting המתאים המצביע לסוג (הזה במקרה int *) נדרש לא שטיפוסו בתים רצף של כתובת מחזירה שהפונקציה כיוון
.(* void) מוגדר
נכון שניגש לוודא כדי המתאים לטיפוס זה את להעביר צריך .(המשתנה לגודל בהתאם) שם שנמצאים לערכים
לבצע וגם ,רגיל מערך אל שניגשים כמו המערך לתאי לגשת נוכל ההתחלה לכתובת גישה למשל) הזה המצביע עם חשבון פעולות
.(השני לתא אותנו תביא 1 ועוד
הגדרה פורמלית -הקצאת זיכרון דינאמית 24
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int main()
{
int *arr=NULL, size,i;
printf(“Enter array size\n”);
scanf(“%d”, &size);
arr = (int *) malloc (size * sizeof(int));
for (i=0; i<size; i++)
scanf(“%d”, &arr[i]);
for (i=0; i<size; i++)
printf(“%4d”, arr[i]);
free(arr);
return 0;
}
הגודל הדרושמהמשתמש את קולטים
מקום בזיכרוןמקצים
ערכים ולהדפיס לקלוט עכשיו אפשר
כמו במערך רגיל, אותם
לכן ניתן למשל , הוא מצביע ולא מערך arr -אבל שימו לב ש)
(כך למקום אחר-את ערכו כך שהוא יצביע אחרלשנות
הקצאת זיכרון למערך בגודל משתנה25
יש לזכור לשחרר את הזיכרון בסיום הטיפול
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
זיכרון מספיק אין כלומר ,נכשלת הזיכרון הקצאת בקשת אם .NULL מחזירה malloc הפונקציה אז ,שביקשנו להקצאה
NULL בספריה שמוגדר 0 שערכו קבוע הוא stdlib.h.
התקבל שביקשנו שהזיכרון לוודא יש הקצאה בקשת כל אחרי. int *arr=NULL,size; printf(“Enter array size\n”); scanf(“%d”, &size); arr = (int *) malloc (size * sizeof(int)); if (arr==NULL) { printf(“Out of memory\n”); return 0; }
בדיקת ההקצאה-הקצאת זיכרון דינאמית26
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
בספריה נמצאות הדינאמית ההקצאה פונקציות כל stdlib.h
void *malloc(unsigned int size);
מקצה הפונקציה size בזיכרון חדשים בתים.
תחילת כתובת את יחזיר הזיכרון הקצאת של מוצלח ביצוע .NULL יוחזר אחרת ,המוקצה הזיכרון
ה פונקציית באמצעות הדינאמית הזיכרון הקצאת- malloc יש ,ריקם אינם המתווספים התאים אך זיכרון תוספת מאפשרת
.כלשהו דיגיטלי זבל בהם קיים כי להניח
malloc -הקצאת זיכרון דינאמית 27
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
מאוד דומה נוספת פונקציה:
void *calloc(unsigned int n, unsigned int size);
של מערך מקצה הפונקציה n בגודל איבר כל ,איברים size בתים, .לאפס אוטומטית מאותחל בזיכרון המוקצה חדש בית כל
הזיכרון תחילת כתובת את יחזיר זיכרון הקצאת של מוצלח ביצוע .NULL יוחזר אחרת ,המוקצה
שימוש דוגמת:
ptr=(int *) calloc(10,sizeof(int));
calloc -הקצאת זיכרון דינאמית 28
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int main()
{
int *arr=NULL, size,i;
printf(“Enter array size\n”);
scanf(“%d”, &size);
arr=(int *) calloc(size,sizeof(int));
for (i=0; i<size; i++)
printf(“%4d”, arr[i]);
for (i=0; i<size; i++)
scanf(“%d”, &arr[i]);
free(arr);
return 0;
}
הגודל הדרושמהמשתמש את קולטים
מקום מאופס בזיכרוןמקצים
ערכים ולהדפיס לקלוט עכשיו אפשר
כמו במערך רגיל, אותם
, הוא מצביע ולא מערך arr -אבל שימו לב ש)
(כך למקום אחר-את ערכו כך שהוא יצביע אחרלשנות ניתן לכן
בגודל משתנה( מאופס)הקצאת זיכרון למערך
מדפיסים את תוכן התאים שהוקצו
29
יש לזכור לשחרר את הזיכרון בסיום הטיפול
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
#include <stdio.h>
#include <stdlib.h>
int main()
}
int *arr=NULL, size,*ptr=NULL;
printf("Enter array size\n");
scanf("%d", &size);
arr=(int *)calloc(size,sizeof(int));
for (ptr=arr; ptr<=&arr[size-1]; ptr++)
printf("%d\n",*ptr);
(מאופס)הקצאת זיכרון למערך בדוגמה לשימוש 30
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
(מאופס)הקצאת זיכרון למערך בדוגמה לשימוש 31
printf("\n");
printf("Enter %d numbers to the array:\n",size);
for (ptr=arr;ptr<=&arr[size-1];ptr++)
scanf("%4d",&(*ptr));
for (ptr=arr;ptr<=&arr[size-1]; ptr++)
printf("%4d",*ptr);
free(arr);
return 0;
{
יש לזכור לשחרר את הזיכרון בסיום הטיפול
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
נוספת שימושית פונקציה:
void *realloc(void *ptr, unsigned int size); אותו) דינאמית שהוקצה בזיכרון לשטח מצביע מקבלת הפונקציה
שהוא) size בתים ומספר ,(malloc/calloc שמחזירות מצביע
.(הדרוש החדש הגודל
החדשה לדרישה בהתאם ההקצאה גודל את משנה הפונקציה.
להגדיל אפשרות ואין ההקצאה את להגדיל הייתה הדרישה אם
והמידע ,אחר במקום חליפי שטח מוקצה ,הנוכחי השטח את
.לשם מועתק
הזיכרון תחילת כתובת את תחזיר לפונקציה מוצלחת קריאה
.NULL יוחזר אחרת ,(השתנתה בהכרח שלא) המוקצה
realloc -הקצאת זיכרון דינאמית 32
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int main()
{
int *arr=NULL, size,new_size,i;
printf(“Enter array size\n”);
scanf(“%d”, &size);
arr=(int *) calloc(size,sizeof(int));
for (i=0; i<size; i++)
printf(“%4d”, arr[i]);
for (i=0; i<size; i++)
scanf(“%d”, &arr[i]);
מהמשתמש את קולטים
הגודל הדרוש
להדפיס את תאי עכשיו אפשר
לתוכם ערכים לקלוט , הזיכרון
..ועוד
משתנהלמערך בגודל ( מאופס)הקצאת זיכרון
מקום מאופס בזיכרוןמקצים
33
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
printf(“Enter new array size\n”);
scanf(“%d”, &new_size);
arr= (int *) realloc(arr, new_size * sizeof(int));
for (i=0; i<new_size; i++)
scanf(“%d”, &arr[i]);
for (i=0; i<new_size; i++)
printf(“%4d”, arr[i]);
free(arr);
return 0;
}
לקלוט למערך בגודלו עכשיו אפשר
.החדש ערכים חדשים
עכשיו ניתן להדפיס את תאי המערך
.בגודלו החדש
בגודל משתנה( מאופס)הקצאת זיכרון למערך 34
מקום חדש לפי הגודל שנקלט מקצים
החדש הנדרש
הגודל מהמשתמש את קולטים
החדש הדרוש
יש לזכור לשחרר את הזיכרון בסיום הטיפול
reallocתוכנית עם : דוגמא
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int *arr=NULL;
int size, new_size;
scanf(“%d”, &size);
arr = (int *) malloc ( size * sizeof(int) ) ;
……...
…… ..
scanf(“%d”, &new_size);
arr=(int *)realloc(arr, new_size*sizeof(int));
………
………
36
- ()free שחרור זיכרון שהוקצה דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
נעלמים הם פונקציה בתוך מוגדרים כשמשתנים כי הוסבר בעבר .סיומה עם אוטומטית
סטטית מוגדרים" אשר משתנים לגבי רק נכון זה". הפונקציה סיום עם נעלמים לא "דינאמית מוקצים" אשר משתנים. שנסביר כפי ,הזאת ההקצאה את לשחרר מתי להחליט באחריותנו
.הבאים בשקפים int main() {
. . func(); .
}
void func()
{
int *ptr=NULL,size=10;
ptr = (int *)malloc(size * sizeof(int));
….
}
37
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
את היטב לבדוק יש אחרת התרחשות כל או אירוע ,ענין מקרה בכל מקום תופסת דינאמית הקצאה כל .דינאמית בהקצאה הצורך
.המקסימלי גודלה ומה נדרשת היא האם לבדוק יש ולכן בזיכרון
דינאמית שהוקצה בזיכרון להשתמש להמשיך צורך ואין במידה .הזה הזיכרון את לשחרר חובה ,בפונקציה
(מצביע) :בפקודה שימוש י"ע נעשה זיכרון שחרורfree .(בהמשך שתודגם)
דינאמית שהקצנו בזיכרון להשתמש להמשיך צורך ויש במידה את להעביר צריכה היא אז ,מסתיימת שהיא אחרי פונקציה בתוך
.לה שקרא למי הקצתה שהיא הזיכרון של הכתובת
38
- ()free שחרור זיכרון שהוקצה דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
ההקצאה את ביצענו שעבורה הכתובת העברת ללא .לכתובת לגשת נוכל לא (למצביע) למשתנה הדינאמית
לשחרר חובה בזיכרון להשתמש כשמסיימים ,מקרה בכל שהקצינו מה כל לשחרר צריך התוכנית סוף שעד כך אותו
.הראשית בתוכנית והן בפונקציות הן דינאמית
המיוצרים במחשבים הזיכרון של ניכרת הגדלה למרות את לשחרר צורך יש עדיין והנייחים הניידים היום
.התפוס הזיכרון
39
- ()free שחרור זיכרון שהוקצה דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
וסיימנו שהקצנו הזיכרון את נשחרר ולא במידה
אזורים המחשב בזיכרון נשאיר אנחנו ,בו להשתמש
שנקרא מה ,נגישים לא בעצם אבל תפוסים שלכאורה
."זיכרון דליפת"
חוסר בגלל המחשב לתקיעת לגרום עשויה זו תופעה
.בזיכרון זמני
(מצביע) הפונקציהfree, בספריה נמצאת stdlib.h,
מצביע שהוא הזיכרון את ומשחררת מצביע מקבלת
.הסוגריים בתוך נמצא (כתובתו) ששמו ,אליו
40
- ()free שחרור זיכרון שהוקצה דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
הפונקציה הגדרת: void free(void ptr)
;free(ptr) :י"ע פשוט השימוש•
הפונקציה אל מועבר אשר המצביע free( ) להכיל חייב .כן לפני דינאמית שהוקצה זיכרון של התחלה-כתובת את
הפונקציות משלוש אחת י"ע הוחזרה זו כתובת:
1. malloc
2. calloc
3. realloc
הפקודה ביצוע אחרי free( ) מבוטלת הזיכרון הקצאת.
41
- ()free שחרור זיכרון שהוקצה דינאמית
שחרור זיכרון שהוקצה דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
השני מהמקום החל למשל ,אחר משהו לשחרר ננסה אם ,דינאמית הוקצה שלא משתנה של כתובת או ,שהוקצה
."תעוף" התוכנית אז
:realloc פקודת לגבי הערות
את בעצמה משחררת היא אז חדש שטח מקצה היא אם1. .הישן השטח
החדש השטח את רק לשחרר המתכנת באחריות2. .שהוקצה הדינאמי הזיכרון לתוספת הכוונה ,שהוקצה
42
הדגמה -שחרור זיכרון שהוקצה דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
void func()
{
int *arr=NULL, size=10;
arr = (int *) malloc(size * sizeof(int));
….
free(arr);
}
43
הדגמה -החזרת זיכרון שהוקצה דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int *func()
{
int *arr=NULL, size=10;
arr = (int *) malloc(size * sizeof(int));
….
….
return arr;
}
44
ושחרורדינאמית דוגמה לשימוש בהקצאה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
#include <stdio.h>
#include <stdlib.h>
void main()
}
float *fptr=NULL; // הגדרת מצביע למספר ממשי
int i, size;
printf("Enter the size:\n"); ריצההעתידי בזמן קליטת גודל המערך//
scanf("%d", &size);
fptr = (float*)malloc(size*sizeof(float)); // למצביעהקצאת זיכרון
if ( fptr == NULL) // הצליחההזיכרון הדינאמי עם הקצאת בדיקה
printf("Not enough memory to allocate buffer\n");
45
ושחרורדינאמית דוגמה לשימוש בהקצאה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
for (i=0; i < size; i++) לאיברי במערךערכים הכנסת //
fptr[i] = i;
// הצגת הערכים באיברי המערך
for(i=0; i < size; i++)
printf("fp[%d] = %f\n",i,*(fptr+i));
//שחרור הזיכרון בסיום השימוש בו
free(fptr);
printf("Free fp was O.K. !!!\n");
return 0;
{
46
הדגמה -החזרת זיכרון שהוקצה דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int *allocate_int_array(int size)
{
int *ptr=NULL;
ptr = (int *) malloc(size * sizeof(int));
if (ptr==NULL)
{
printf(“Out of memory”);
return 0;
}
return ptr;
}
בגודל שלמים ' הפונקציה מקצה דינאמית מערך של מס
ומחזירה את כתובת , שההקצאה הצליחהבודקת , המבוקש
.שהוקצההמערך
שלא ,הזה המערך כתובת את להחזיר אפשר
,דינאמית הוקצה הוא כי הפונקציה בסוף משוחרר
לשחררו לדאוג צריך לפונקציה שקרא מי אבל
.בו השימוש בסיום
47
מצביעים לא מאותחלים
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
אינם מצביעים גם משתנה כל שכמו ,לזכור חשוב
ערך להם לתת וצריך ,שלהם בהגדרה מאותחלים
.התחלתי
בלי במצביע שנמצאת לכתובת לגשת וננסה במידה
."תעוף" התוכנית ,התחלתי ערך לו שנתנו
למשל:
int *ptr;
*ptr=10;
!!!אותחלה לא ptr -של הכתובת
ולכן לא ניתן לבצע לה השמה
50
מצביעים לא מאותחלים
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
בו שמנו אם רק במצביע שנמצאת לכתובת לגשת ניתן
דינאמית שהוקצה שטח של או משתנה של כתובת קודם
:י"ע וזאתint i, size=10;
int *ptr=NULL;
ptr=&i;
:הגדרה כזוי "וע
ptr=(int *) malloc (size*sizeof(int));
51
מצביעים לא מאותחלים
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
י "אפשרות נוספת שראינו למתן ערך למצביע היא ע, כזכור
.הכנסת כתובת של מערך או של מצביע אחר אליו
int arr[10];
int *ptr=NULL;
ptr=arr; //ptr=&arr[0];
הפעולה תעבוד באופן תקין בהנחה שהמצביעptr הוגדר לפני
:י ביצוע הפקודה"ע ל"שתי השורות הנ
int *ptr=NULL;
ל מאפשרת השמת כתובת בתוך "ההגדרה הנptr שהוא החלק
.מוגדר כמצביע ptr*במצביע המסוגל לקבל כתובת כאשר
52
קבועהמחרוזת
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
על למצביע קבועה מחרוזת ונציב במידה char בלי תתרחש לא אז (מהקלט מחרוזת לא) אותו לאתחל
הקצאה בוצעה שלא אפילו ,התוכנית של "תעופה" ידי-על מחרוזות להעתיק ניתן שלא ואפילו כלשהי .השמה
כתובות של השמה ביצוע בעצם שזו כיוון מתרחש זה:
שהוא קבועה מחרוזת כל בזיכרון שומר שהקומפיילר כיוון כלשהי כתובת יש כבר הזאת למחרוזת ,בתוכנית מוצא
רק המצביע ולכן מאוחסנת היא שבה כתובת ,בזיכרון .לשם מצביע
53
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
למשל אפשר לכתוב:
char *ptr_c=NULL, *ptr_s=NULL;
ptr_c=“Hello!”;
ptr_s=“Hello!”;
המשמעות היא ששני המצביעים מצביעים על אותה מחרוזת.
קומפיילרים רבים לא יאפשרו לשנות מחרוזת כזו.
כל שינוי כזה עשוי להשפיע על כל הופעות המחרוזת בתוכנית .
‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘!’ ‘\0’ ptr_s
ptr_c
קבועהמחרוזת 54
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
ידי על וזאת מבנים של למערך דינאמית זיכרון הקצאת לבצע ניתן
:מבנה מטיפוס שהוא למצביע זיכרון הקצאת
חדש מבנה יצרת – ראשון שלב•
החדש המבנה מטיפוס מצביע הגדרת – שני שלב•
למצביע דינאמי זיכרון הקצאת – שלישי שלב•
הקצאה י"ע שנוצר החדש למערך נתונים קליטת – רביעי שלב•
.והדפסתם סטטי גודל י"ע ולא דינאמית
למערך של מבנים הקצאת זיכרון דינאמית56
הגדרת מבנה –שלב ראשון
Shayke Bilu PhD SCE-Chapter-10-Structs
נגדיר מבנה של מספר מורכב:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
double x, y;
}Point;
57
double x
Point
double y
הפעלת פונקציות לקלט ופלט -שלב רביעי
Shayke Bilu PhD SCE-Chapter-10-Structs
void Fillarray(Point *arr, int size)
{
int i;
for(i=0;i<size;i++)
scanf(“%lf %lf”,&arr[i].x,&arr[i].y);
}
void Printarray(Point *arr, int size)
{
int i;
for(i=0;i<size;i++)
printf(“X=%lf \tY=%lf”,arr[i].x,arr[i].y);
}
58
שלב שני ושלישי הגדרת מצביע והקצאת זיכרון
Shayke Bilu PhD SCE-Chapter-10-Structs
void main()
{
Point *arr=NULL;
int size,i;
printf(“Enter size for array\n”);
scanf(“%d”, &size);
arr =(Point *) malloc (size*sizeof(Point));
Fillarray(arr,size);
Printarray(arr,size);
free(arr);
}
59
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
היה היום עד שלנו התוכנית את ששימש המקסימאלי הזיכרון• .בתוכנית המשתנים וסוגי טיפוסי הגדרת פי על מראש קבוע
,התרגום שלב את עברה שהתוכנית לאחר ,התוכנית הרצת לפני• במהלך לשינוי ניתן ואינו נקבע גודלם שבתוכנית המערכים כל
!התוכנית ריצת
:אפשריות בעיות•
הסטודנטים כל ציוני את לשמור 100 בגודל מערך הגדרנו אם1.
?נעשה מה נוסף סטודנט מגיע וכעת
!המערך גודל את לשנות ניתן ולא כתובה כבר התוכנית2.
.דרישה פי על תאים עוד לייצר המסוגל יצירתי פתרון נצטרך3.
סיכום - הקצאת זיכרון דינאמית61
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
זיכרון תוך לנו להקצות מאפשרת Cשפת
וכך להגדיר מערכיםריצת התוכנית כדי
: ומבנים אחרים בצורה דינאמית
int main()
{
int arr[10];
arr[6] = 7;
}
10 int's
int main()
{
int *arr,size=10;
arr = (int*) malloc(size * sizeof(int));
arr[6] = 7;
}
a 10 int’s
6024
6024
62
סיכום - הקצאת זיכרון דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
י המתכנת צריך להיות משוחרר "כל שטח זיכרון שהוקצה ע• . בסיום השימוש בו
חייבים תמיד להחזיק את כתובת האזור שהוקצה על מנת לכן • .שנוכל לשחרר אותו בסיום השימוש
int main()
{
int *arr,size=10;
arr = (int*) malloc(size * sizeof(int));
arr[6] = 7;
free(a);
}
a 6024 6024
63
סיכום - הקצאת זיכרון דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
אם נרצה להוסיף איבר חדש נוסף נצטרך להעתיק את כל במערך • . הקצנואשר האיברים הישנים למערך גדול יותר
.המערך הישןאליו את ונעתיק מערך חדש נקצה •
int's 10 קיים
חדש3 int's
חדש
64
קיים
סיכום - הקצאת זיכרון דינאמית
:stdlib.h -הפונקציות נמצאות ב
void *malloc(size * sizeof( ));
.הקצאת בתים בגודל נדרש בזיכרון באופן דינאמי•
, קריאה להקצאה מוצלחת מחזירה כתובת בסיס חדשה• .NULLאחרת מוחזרת כתובת
מאפשרת שימוש בכתובת שהוחזרה ככתובת להתחלת • .מערך חד ממדי או דו ממדי
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
65
סיכום - הקצאת זיכרון דינאמית
:stdlib.h -הפונקציות נמצאות ב
void *calloc(size, sizeof( ))
size_el של בגודל כל חד של אלמנטים הקצאת מערך•
.לאפס כל תא שהוקצה בזיכרון מאותחל•
, מחזירה כתובת בסיס חדשה קריאה להקצאה מוצלחת• .NULL יוחזר אחרת
מאפשרת שימוש בכתובת שהוחזרה ככתובת להתחלת • .שערכך מאופסים ממדימערך חד ממדי או דו
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
66
סיכום - הקצאת זיכרון דינאמית
:stdlib.h -נמצאות בהפונקציות
void free(void *ptr)
.מבטל את הקצאת הזיכרון•
.מקיים מצביע על המיקום בו הוקצה הזיכרון הקודם•
.מוחק את הכתובת הקודמת הנמצאת במצביע/משחרר•
מונע אפשרות גישה לכתובת המערך שהוקצתה למצביע • .המשוחרר
מאפשרת שימוש חוזר בכתובת זו לצורכי הקצאת זיכרון • . עתידית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
67
סיכום - הקצאת זיכרון דינאמית
:stdlib.h -נמצאות בהפונקציות
void *realloc(void ptr, newsize * sizeof())
.מקצה מחדש מקום בזיכרון לצורך שינוי גודל קודם•
newsizeהמקום החדש בזיכרון הוא על פי הגודל של • .ptrוהחל מהמצביע
מאפשרת הגדלה או הקטנה של כמות התאים בזיכרון • .אשר מוקצים דינאמית החל מכתובת מצביע התחלתי
י "מצביע ההתחלתי נעשתה הקצאת זיכרון קודמת על•malloc אוcalloc.
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
68
סיכום - הקצאת זיכרון דינאמית
הקצאת זיכרון דינאמית למערך חד ממדי
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
#include <stdio.h>
#include <stdlib.h>
void FillArray(int arr[], int size);
void PrintArray(int arr[], int size);
ספריות והצהרות על
פונקציות
69
הקצאת זיכרון דינאמית –דוגמא
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int main()
{
int *arr, size;
printf("Enter the size:\n");
scanf("%d", &size);
arr = (int *)calloc(size, sizeof(int));
FillArray(arr, size);
PrintArray(arr, size);
free(arr);
return 0;
}
תוכנית
ראשית
70
הקצאת זיכרון דינאמית –דוגמא
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
void FillArray(int arr[], int size)
{
int i;
for(i = 0; i < size; i++)
{
arr[i] = rand()%100 + 1;
}
}
מילוי המערך החד ממדי
במספרים אקראיים
71
הקצאת זיכרון דינאמית –דוגמא
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
void PrintArray(int arr[], int size)
{
int i;
for(i = 0; i < size; i++)
{
printf("%3d ", arr[i]);
if (i % 10 == 0)
printf("\n");
}
}
הדפסת המערך
החד ממדי
72
קליטת מספר לא ידוע של תווים
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
תווים של רצף מהמשתמש קלט המקבלת תוכנית כתוב .Enter על בלחיצה המסתיים מראש ידוע אינו שאורכו
מההתחלה שנקלט התווים אוסף את תדפיס התוכנית .לסוף
מהסוף שנקלט התווים אוסף את תדפיס התוכנית .להתחלה
הנקלט לתו מקום סיבוב בכל דינאמית להקצות יש :רמז .הקלט בסוף ’0\‘ השמת י"ע המחרוזת סגירת לוודא ויש
ברקורסיה להשתמש ,מצב בשום ,אין!!!.
74
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
#include <stdio.h>
#include <stdlib.h>
void main()
{
char *input=(char *)malloc(1),ch;
int i,size=1,current=0;
scanf("%c",&ch);
פתרון-קליטת מספר לא ידוע של תווים75
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
while (ch != '\n')
{
if (current + 1 == size)
input = (char *)realloc(input, size++);
הגדלת הקצאת הזיכרון באחד כל סיבוב והצבת התו במקום המוקצה//
input[current++] = ch;
scanf("%c",&ch);
} //while
פתרון-קליטת מספר לא ידוע של תווים76
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
input[current]='\0';
puts("Original String:");
puts(input);
puts(“Reverse String:");
puts(strrev(input));
free(input);
}
פתרון-קליטת מספר לא ידוע של תווים77
הקצאת זיכרון דינאמית למערך דו ממדי
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
78
:ממדי כמערך של מערכים-ייצוג מערך דו
חד ממדים המייצגים מערכים
אוסף של עמודות המהווה שורה
בעצם מצביע כאשר כל –מערך של מצביעים
המתאימה שהחל ממנה מתחילות לשורה מצביע
העמודות המרכיבות את השורה
Matrix :
הגדרת מערך דו ממדי בהקצאת זיכרון
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
כתוב תוכנית הקולטת נתונים מספריים למטריצה דו ממדיתפלט , קלט נתונים, בגודל דינאמי שמקבל הקצאת זיכרון
.נתונים
#include <stdio.h>
#include <stdlib.h>
void FillArray(int **arr, int size);
void PrintArray(int **arr, int size);
ספריות והצהרות על
פונקציות
79
הגדרת מערך דו ממדי בהקצאת זיכרון
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
int main() {
int **arr, size,i; printf("Enter the size:\n"); scanf("%d", &size); arr = (int **)calloc(size, sizeof(int)); for (i=0;i<size;i++) *(arr+i)=(int *)calloc(size,sizeof(int)); FillArray(arr, size); PrintArray(arr, size); free(arr); return 0; }
תוכנית
ראשית
80
פונקציית קלט הנתונים למטריצה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
void FillArray(int **arr, int size)
{
int i,j;
for(i = 0; i < size; i++)
{
for(j = 0; j < size; j++)
{
*(*(arr+i)+j)= rand()%100 + 1;
}
}
}
קלט המערך
הדו ממדי
81
פונקציית הדפסת הנתונים של המטריצה
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
void PrintArray(int **arr, int size)
{
int i,j;
for(i = 0; i < size; i++)
{
for(j = 0; j < size; j++)
{
printf("%3d ", *(*(arr+i)+j));
if (i % 10 == 0)
printf("\n");
}
}}
פלט המערך
הדו ממדי
82
סיכום -הקצאת זיכרון דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
אפשר להקצות מקום בזיכרון בזמן הריצה .
גודל שלא ידוע )אפשר ליצור מערך בגודל שתלוי בקלט (.מראש
בספריהstdlib.h נמצאות הפקודות:
malloc, calloc, realloc, free().
הנשמרת , כשמקצים מקום בזיכרון מוחזרת הכתובת שלובהתאם לסוג המשתנה שיבחר לשמירה במקום )במצביע
(. הזה
84
סיכום -הקצאת זיכרון דינאמית
Shayke Bilu PhD SCE-Chapter-11-Dynamic Memory Allocation
אפשר אבל ,החדש מערך/למשתנה שם לתת אפשר-אי .המצביע דרך אליהם לגשת
את כשמסיימים שהוקצה זיכרון לשחרר לזכור צריך . בו השימוש
תגרום מאותחל לא במצביע שנמצאת לכתובת כתיבה .אותו לאתחל לזכור צריך – "תעופה" -ל תמיד
לאפס ניתן מסכם שדה על להצביע מיועד אשר מצביע .NULL :הערך השמת י"ע
85
Shayke Bilu PhD
87
תרגילי כיתה
ידי על שהוזנו אלמנטים n של סכום את המחשבת תוכנית כתוב1.
באמצעות דינמי זיכרון להקצות ,זו תכנית לביצוע .משתמש
.()malloc -ה פונקציית
ידי על שהוזנו אלמנטים nשל סכום את המחשבת תוכנית כתוב 2.
באמצעות דינמי זיכרון להקצות ,זו תכנית לביצוע .משתמש
.()calloc -ה פונקציית
לגבי מושג למתכנת אין בו למצב מענה הנותנת תוכנית כתוב3.
זה במקרה .במחרוזת לאחסן שצריך הנקלט הטקסט של האורך
מכן ולאחר נדרש זיכרון כמה להגדיר מבלי מצביע להגדיר עליך
.הנקלטת המחרוזת תיכנס שאליו זיכרון יוקצה דרישה בסיס על
.שנקלטה המחרוזת תודפס הקליטה בסיום
SCE-Chapter-11-Dynamic Memory Allocation
Shayke Bilu PhD
88
תרגילי כיתה
לשנות צורך יש בו במצב המטפל הקודמת לתוכנית עדכון כתוב4.
של הקטנה או הגדלה לבצע כלומר הקליטה לאחר הגודל את
.realloc)( בפונקציה שימוש י"ע הזיכרון
שלמים מספרים של ממדי דו מערך המייצרת תוכנית כתוב5.
כך אחר .למצביע במצביע שימוש י"ע זיכרון הקצאת המקבל
ותדפיס אקראיים במספרים שנוצר המערך את תמלא התוכנית
.!!!בלבד במצביעים בשימוש והכל ,אותו
סכום את ומחשבת שלמים מספרים אינסוף הקולטת תוכנית כתוב6.
ביותר והקטן ביותר הגדול את הממוצע את ,המספרים כל
התוכנית מספרים 4 של קליטה לאחר .שנקלטו מהמספרים
.-1 להקליד יש לסיום .שתיים פי המוקצה הזיכרון את מגדילהSCE-Chapter-11-Dynamic Memory Allocation
Shayke Bilu PhD
89
תרגילי כיתה
:הבאות המשימות את המבצעת תוכנית כתוב7.
(aממדי חד/ממדי דו למערך דינאמי זיכרון הקצאת מבצעת.
(bהדו למערך 1000 -ל 1 בין אקראיים מספרים של הכנסה מבצעת
.בפונקציה שימוש י"ע ממדי
(cמשוכללים מספרים קיימים שנוצר במערך האם בדיקה מבצעת
.בפונקציה שימוש י"ע אותם ומדפיסה
(dבפונקציה שימוש י"ע ממדי הדו המערך של הדפסה מבצעת.
כל לסכום השווה טבעי מספר הוא משוכלל מספר
.עצמו המספר מלבד שלו הטבעיים המחלקים
ואחריו ,1+2+3=6 הוא הראשון המשוכלל המספר
.8128ו־ 496 ,1+2+4+7+14=28 באים
SCE-Chapter-11-Dynamic Memory Allocation
Shayke Bilu PhD
90
תרגילי כיתה
דינאמי ממדי-דו במערך שימוש המדגימה תוכנית כתוב8.
גודל בעל ממדי דו מערך להגדיר כשרוצים :תזכורת .מחרוזתי
גודל .למערכים מצביעים של מערך ליצור עלינו ,משתנה
המערך גודל את נגדיר ולכן התכנית בתחילת ידוע לא המערך
( )calloc או ( )malloc :פונקציית באמצעות
מצביע כל נאתחל מכן ולאחר ,מצביעים של מערך נאתחל בתחילה
.הרצוי type -ה של מערך להיות
בגודל ים-char של ממדי דו מערך לייצר עלינו זה בתרגיל ,למשל
עד A -מ אקראית אות תופיע תא שבכל כך המשתמש י"ע המוגדר
Z או a עד z.
.ascii -ה מטבלת התווים כתובות בערכי להשתמש יש ,רמזSCE-Chapter-11-Dynamic Memory Allocation
Shayke Bilu PhD
91
תרגילי כיתה
.ממדי דו למערך דינאמית זיכרון הקצאת המבצעת תוכנית כתוב9.
-ל 1 בין אקראיים במספרים המערך את תמלא נוספת פונקציה
וזאת נוספת בדיקה לפונקציה יועברו וגודלו המערך כתובת .100
ותדפיס תחשב ,הבדיקה פונקציית ,הפונקציה .מספרים 2 עם יחד
ללא הראשון במספר המתחלקים במערך האיברים כמות את
ללא השני במספר המתחלקים האיברים כמות ואת שארית
.שארית
:דוגמא
-ו 2 והמספרים {{11 ,10 ,9},,{8 ,7 ,6{,}5 ,4 ,3{,}7,1,2}} המערך עבור
,8 ,6 ,4 ,2) בו מתחלקים ערכים 5 ,2 המספר שעבור תחזיר הפונקציה ,3
בו מתחלקים מספרים 3 -ש הפונקציה תחזיר 3 המספר ועבור (10
(3,6,9). SCE-Chapter-11-Dynamic Memory Allocation
Shayke Bilu PhD
92
תרגילי כיתה
לקליטת ממדי חד מערך המקצה פונקציה הכוללת תוכנית כתוב10.
.הממוצע את ומדפיסה מחשבת ציונים אליו קולטת ,ציונים
לאחר .המשתמש בקשת לפי ,המערך גודל את משנה כך-אחר
מחדש יחושב הממוצע ,חדשים ציונים וקריאת בגודל שינוי כל
.הממוצע מעל היו ציונים כמה ויודפס יחושב וכן
:לתוכנית הערות
גודל את לשנות המאפשרת do..while בלולאת להשתמש מומלץ
.שרוצים פעמים כמה המערך
נפרדת פלט פונקציית ,נפרדת קלט פונקציית להגדיר מומלץ
.נפרדת חישוב ופונקציית
SCE-Chapter-11-Dynamic Memory Allocation