מבוא כללי למדעי המחשב הקצאת זיכרון דינאמית www.cs.tau.ac.il/courses/cs4math/09b.

Slides:



Advertisements
Similar presentations
ממיבחניםC שאלות ++.
Advertisements

מבוא למדעי המחשב לתעשייה וניהול
הרצאה 04 הקצאות דינאמיות קרן כליף.
קורס תכנות שיעור שנים-עשר: ניהול זיכרון 1. הקצאת זיכרון דינאמית עד עכשיו עשינו "הקצאה סטטית" הגדרנו את משתני התוכנית כבר כשכתבנו אותה הקומפיילר הקצה עבורם.
הקצאות דינאמיות קרן כליף.
1 מבוא למדעי המחשב הקצאה דינאמית. 2 הקצאת זיכרון דינאמית  כאשר אנו משתמשים במערכים, אנו מקצים אוטומטית את הזיכרון המקסימלי שנצטרך.  בפועל, אנו משתמשים.
תכנות מונחה עצמים Object Oriented Programming (OOP) אתגר מחזור ב'
תרגול מס' 2  העברת פרמטרים לתוכניות ב-C  קלט ופלט ב-C  I/O redirection  זיכרון דינמי  מצביעים  מערכים  גישות לא חוקיות לזיכרון.
רקורסיות נושאי השיעור פתרון משוואות רקורסיביות שיטת ההצבה
תכנות תרגול 11 שבוע : מבנים מטרת המבנים היא לאפשר למתכנת להגדיר טיפוסי משתנים חדשים אשר מתאימים ספציפית לבעיה שאותה התוכנית פותרת. מטרת המבנים.
תכנות תרגול 9 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
שאלות חזרה לבחינה. שאלה דיסקים אופטיים מסוג WORM (write-once-read-many) משמשים חברות לצורך איחסון כמויות גדולות של מידע באופן קבוע ומבלי שניתן לשנותו.
מבוא לשפת C חידות ונקודות חשובות נכתב על-ידי יורי פקלני. © כל הזכויות שמורות לטכניון – מכון טכנולוגי לישראל.
מבוא למדעי המחשב תרגול 8 - מחרוזות שעת קבלה : יום שני 11:00-12:00 דוא " ל :
חורף - תשס " ג DBMS, צורות נורמליות 1 צורה נורמלית שלישית - 3NF הגדרה : תהי R סכמה רלציונית ותהי F קבוצת תלויות פונקציונליות מעל R. R היא ב -3NF.
מבוא כללי למדעי המחשב תרגול. הבית האדום כתובת : רחוב קוקוריקו 2 הבית הירוק כתובת : רחוב קוקוריקו 4 הבית הצהוב כתובת : רחוב קוקוריקו 1 הבית הורוד כתובת.
תכנות תרגול 9 שבוע : מערכים int a; a=5; int a[10]; a[2] = 5; 5 a a[0] a[1] a[2] a[9]  5 משתנה בודד מערך גישה למשתנה השלישי במערך.
תוכנה 1 - חזרה שולי לב יהודי 2 Arrays and Strings מערך - אוסף משתנים בעלי שם משותף. הפנייה לכל איבר נעשית ע ” י אינדקס. ב -C מערך מוגדר.
מבוא למדעי המחשב © אריק פרידמן 1 מצביעים כמערכים דוגמה.
שיעור שישי: מערכים ופונקציות
חלון הפקודות מיועד לבצע פעולה אחת בכל פעם. כיצד אפשר לבצע רשימת פקודות או אפליקציות מורכבות ?
מבוא למדעי המחשב מחרוזות, מצביעים וכתובות
תכנות תרגול 6 שבוע : הגדרת פונקציות return-value-type function-name(parameter1, parameter2, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
מבוא כללי למדעי המחשב שיעור 5
תכנות – שיעור 7. חזרה -מערכים נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו מספר רב של משתנים זהים נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו מספר רב של משתנים.
תכנות תרגול 14 שבוע:
תכנות תרגול 10 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
קורס תכנות – סימסטר ב ' תשס " ח שיעור שישי: מערכים
מבוא כללי למדעי המחשב רשימות מקושרות
Data Structures, CS, TAU, Perfect Hashing 1 Perfect Hashing בעיה : נתונה קבוצה S של n מפתחות מתחום U השוואה ל - Hash : * טבלה קבועה (Hash רגיל - דינאמי.
1 Data Structures, CS, TAU, Perfect Hashing בעיה: נתונה קבוצה S של n מפתחות מתחום U השוואה ל- Hash : * טבלה קבועה (Hash רגיל - דינאמי) * רוצים זמן קבוע.
מערכים עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר int grade1, grade2, …, grade20; int grade1, grade2, …, grade20;
תכנות מונחה עצמים Object Oriented Programming (OOP) אתגר מחזור ב' Templates תבניות.
מבוא למדעי המחשב תרגול 3 שעת קבלה : יום שני 11:00-12:00 דוא " ל :
Last time on Clang משתנה: "פתק" המשמש את המחשב לשמירת מידע. לכל משתנה יש שם וטיפוס כללים לשמות משתנים –חייבים להכיל רק אותיות, מספרים ו '_' –חייבים להתחיל.
תוכנה 1 - תרגול שיעור 10 Pointers (2) שולי לב יהודי
1 מבוא למדעי המחשב סיבוכיות. 2 סיבוכיות - מוטיבציה סידרת פיבונאצ'י: long fibonacci (int n) { if (n == 1 || n == 2) return 1; else return (fibonacci(n-1)
מבוא כללי למדעי המחשב תרגול 7. מבנים מטרת המבנים היא לאפשר למתכנת להגדיר טיפוסי משתנים חדשים אשר מתאימים ספציפית לבעיה שאותה התוכנית פותרת. מטרת המבנים.
מבוא למדעי המחשב תרגול 12 – הקצאת זיכרון דינאמית שעת קבלה : יום שני 11:00-12:00 דוא " ל :
תכנות תרגול 8 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
Structure. מה לומדים היום ? דרך לבנות מבנה נתונים בסיסי – Structure מייצר " טיפוס " חדש מתאים כאשר רוצים לאגד כמה משתנים יחד דוגמאות : עובד : שם, טלפון,
הגדרת משתנים יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר.
קורס תכנות שיעור שמיני: הקצאת זיכרון דינאמית, הצצה לייצוג ועיבוד תמונות 1.
מבוא למדעי המחשב הרצאה 7: מבנים מבוסס על השקפים שנערכו שי ארצי, גיתית רוקנשטיין, איתן אביאור, וסאהר אסמיר, מיכאל אלעד, רון קימל וניר אילון עדכון אחרון.
קורס תכנות שיעור עשירי: מיונים, חיפושים, וקצת סיבוכיות חישוב.
מבנים קרן כליף. ביחידה זו נלמד :  מהו מבנה (struct)  איתחול מבנה  השמת מבנים  השוואת מבנים  העברת מבנה לפונקציה  מבנה בתוך מבנה  מערך של מבנים.
מבוא למדעי המחשב לתעשייה וניהול הרצאה 6. מפעל השעווה – לולאות  עד עכשיו  טיפלנו בייצור נרות מסוג אחד, במחיר אחיד  למדנו להתמודד עם טיפול במקרים שונים.
הגדרת משתנים יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016.
מחרוזות – הטיפוס String
Programming Arrays.
מבוא למדעי המחשב סיבוכיות.
הקצאות דינאמיות בשילוב מבנים
מערכים ומצביעים הקצאה דינאמית של מערכים דו-מימדיים
מצביעים קרן כליף.
תירגול 14: מבני נתונים דינאמיים
קורס תכנות – סמסטר ב' תשס"ח
הקצאות דינאמיות קרן כליף.
מבנים קרן כליף.
שיעור שישי: מחרוזות, מצביעים
Introduction to Programming in C
מצביעים קרן כליף.
מבוא כללי למדעי המחשב פונקציות
הקצאת זיכרון דינאמית מבוא כללי למדעי המחשב
מבוא כללי למדעי המחשב תרגול 6
סוגי משתנים קרן כליף.
מערכים של מצביעים הקצאה דינאמית
Programming in C תרגול Introduction to C - Fall Amir Menczel.
תוכנה 1 תרגול 13 – סיכום.
מבוא למדעי המחשב מצביעים.
תירגול 8:מצביעים והקצאה דינאמית
Presentation transcript:

מבוא כללי למדעי המחשב הקצאת זיכרון דינאמית

מבנים - תזכורת אפשר להגדיר בשפת C טיפוסי משתנים חדשים, שמתאימים יותר לבעיה שרוצים לפתור. אפשר להגדיר בשפת C טיפוסי משתנים חדשים, שמתאימים יותר לבעיה שרוצים לפתור. למשל: מס' מרוכב, נקודה במישור, מלבן, סטודנט... למשל: מס' מרוכב, נקודה במישור, מלבן, סטודנט... טיפוס חדש כזה נקרא "מבנה". טיפוס חדש כזה נקרא "מבנה". מבנה מוגדר על-ידי אוסף של משתנים מטיפוסים שכבר קיימים ("שדות"). מבנה מוגדר על-ידי אוסף של משתנים מטיפוסים שכבר קיימים ("שדות"). למשל מבנה ליצוג נקודה במישור יכלול שני שדות שהם מספרים ממשיים: קואורדינטת X וקואורדינטת Y. למשל מבנה ליצוג נקודה במישור יכלול שני שדות שהם מספרים ממשיים: קואורדינטת X וקואורדינטת Y. מבנה ליצוג סטודנט יכול לכלול שם, ת.ז., טלפון, וכו'. מבנה ליצוג סטודנט יכול לכלול שם, ת.ז., טלפון, וכו'.

תזכורת: דוגמאות שראינו למבנים נקודה במישור: נקודה במישור: struct point { double x; double y; }; מספר מרוכב: מספר מרוכב: struct complex { double real; double img; };

תזכורת: עוד דוגמא שראינו מבנה ליצוג סטודנט: מבנה ליצוג סטודנט: struct student{ struct student{ int id; int id; char name[40]; char name[40]; double average; double average;};

תזכורת: מבנים – הגדרה וגישה #include<stdio.h> struct point { double x; double y; }; int main() { struct point P1,P2; struct point P1,P2; P1.x = 6; P1.x = 6; P1.y = 7; P1.y = 7; P2.x = 4; P2.x = 4; P2.y = 2; P2.y = 2; printf(“%g\n”, P1.y); printf(“%g\n”, P1.y); return 0; return 0;} P1P xyxy

תזכורת: שם מקוצר לטיפוס משתנה חדש struct point { double x; double y; }; typedef struct point point; זה מאפשר לכתוב point במקום לכתוב struct point. אפשר גם לרשום את זה כך: typedef struct point { double x; double y; } point; שם חדש טיפוס קיים

תזכורת: התכונות של מבנים למשתנים מטיפוס חדש (מבנה) יש חלק גדול מהתכונות של משתנים מטיפוסים רגילים: למשתנים מטיפוס חדש (מבנה) יש חלק גדול מהתכונות של משתנים מטיפוסים רגילים: אפשר לבצע השמה בין שני משתנים מאותו טיפוס מבנה p1=p2; אפשר לבצע השמה בין שני משתנים מאותו טיפוס מבנה p1=p2; גם שדה שהוא מערך יועתק אל המשתנה החדש (לא רק כתובת המערך)גם שדה שהוא מערך יועתק אל המשתנה החדש (לא רק כתובת המערך) אפשר להגדיר מערך של מבנים מטיפוס כלשהו (למשל point a[10]). אפשר להגדיר מערך של מבנים מטיפוס כלשהו (למשל point a[10]). אפשר להעביר ולהחזיר מבנה מפונקציה. אפשר להעביר ולהחזיר מבנה מפונקציה. מה שמועבר הוא עותק של המבנה (גם מערכים שנמצאים בתוכו יועתקו).מה שמועבר הוא עותק של המבנה (גם מערכים שנמצאים בתוכו יועתקו). אפשר להגדיר מצביע למשתנה מטיפוס מבנה (למשל complex *). אפשר להגדיר מצביע למשתנה מטיפוס מבנה (למשל complex *). שדה של מבנה יכול להיות מטיפוס שהוא מבנה (אחר). שדה של מבנה יכול להיות מטיפוס שהוא מבנה (אחר). לא ניתן להשתמש בפעולות החשבון וההשוואה הרגילות על מבנים - יש להגדיר פונקציות עבורן בהתאם לצורך. לא ניתן להשתמש בפעולות החשבון וההשוואה הרגילות על מבנים - יש להגדיר פונקציות עבורן בהתאם לצורך.

תזכורת: מבנים ומצביעים אפשר להגדיר מצביע גם לטיפוס שהוא מבנה (כתובת ההתחלה של מבנה היא כתובת השדה הראשון שלו). אפשר להגדיר מצביע גם לטיפוס שהוא מבנה (כתובת ההתחלה של מבנה היא כתובת השדה הראשון שלו). נשתמש בזה כדי לשנות מבנה מתוך פונקציה, או כדי לחסוך את העתקת השדות בהעברת המבנה אליה. נשתמש בזה כדי לשנות מבנה מתוך פונקציה, או כדי לחסוך את העתקת השדות בהעברת המבנה אליה. למשל: למשל: struct point P={5,6}; struct point *ptr; ptr = &P ; 5 6 P ptr P.x P.y

מצביעים ומבנים – גישה לשדות המבנה כדי להגיע לשדות של P דרך ptr שמצביע על P, אפשר להשתמש ב- * כרגיל: כדי להגיע לשדות של P דרך ptr שמצביע על P, אפשר להשתמש ב- * כרגיל: (*ptr).x = 3; שקול ל- P.x = 3 (*ptr).x = 3; שקול ל- P.x = 3 (*ptr).y = 7; שקול ל- P.y = 7 (*ptr).y = 7; שקול ל- P.y = 7 אבל בדרך-כלל נשתמש לצורך זה בסימון מקוצר: חץ <- אבל בדרך-כלל נשתמש לצורך זה בסימון מקוצר: חץ <- ptr->x = 3; שקול ל- P.x = 3 ptr->x = 3; שקול ל- P.x = 3 ptr->y = 7; שקול ל- P.y = 7 ptr->y = 7; שקול ל- P.y = 7 כלומר משמעות החץ היא גישה לשדה במבנה שמצביעים עליו. כלומר משמעות החץ היא גישה לשדה במבנה שמצביעים עליו. (צריך סוגריים כי אחרת לנקודה יש קדימות) (צריך סוגריים כי אחרת לנקודה יש קדימות)

תזכורת: מבנים ומצביעים struct point P={5,6}; struct point *ptr; ptr = &P ; 5 6 P ptr P.x P.y ptr -> y ptr -> x אם השדה x היה בעצמו מטיפוס מצביע למבנה אחר שיש בו שדה a, אז היה אפשר לרשום ptr->x->a אם השדה x היה בעצמו מטיפוס מצביע למבנה אחר שיש בו שדה a, אז היה אפשר לרשום ptr->x->a

הקצאת זיכרון דינאמית

עד עכשיו תמיד הגדרנו בדיוק איזה משתנים יהיו לנו בתוכנית כבר כשכתבנו אותה (זה נקרא "הקצאה סטטית"). עד עכשיו תמיד הגדרנו בדיוק איזה משתנים יהיו לנו בתוכנית כבר כשכתבנו אותה (זה נקרא "הקצאה סטטית"). בפרט, בהגדרת מערך קבענו את גודלו, ולא יכולנו לשנות אותו בזמן הריצה (אם הגודל לא היה ידוע מראש הנחנו חסם עליון). בפרט, בהגדרת מערך קבענו את גודלו, ולא יכולנו לשנות אותו בזמן הריצה (אם הגודל לא היה ידוע מראש הנחנו חסם עליון). למשל: למשל: int main() int main() { int a[10]; } עבור המערך הזה יוקצו עשרה תאים בזיכרון, ולא נוכל להגדיל אותו תוך כדי הרצת התוכנית. עבור המערך הזה יוקצו עשרה תאים בזיכרון, ולא נוכל להגדיל אותו תוך כדי הרצת התוכנית.

הקצאת זיכרון דינאמית לפעמים נירצה להגדיר משתנים נוספים בזמן הריצה, בפרט להגדיר מערך בגודל שתלוי בקלט מהמשתמש (יתכן שלא ידוע מראש חסם-עליון על הגודל). לפעמים נירצה להגדיר משתנים נוספים בזמן הריצה, בפרט להגדיר מערך בגודל שתלוי בקלט מהמשתמש (יתכן שלא ידוע מראש חסם-עליון על הגודל). אפשר לממש דבר כזה ב- C: יש פונקציה בשם malloc, שמקצה מקום בזיכרון תוך כדי ריצת התוכנית (הגודל יכול להיות תלוי בקלט). אפשר לממש דבר כזה ב- C: יש פונקציה בשם malloc, שמקצה מקום בזיכרון תוך כדי ריצת התוכנית (הגודל יכול להיות תלוי בקלט). היא נמצאת בספריה stdlib.h. היא נמצאת בספריה stdlib.h. מעבירים לפונקציה הזאת גודל זיכרון מבוקש (בבתים), והיא מחזירה מצביע לאזור בגודל הזה שהוקצה בזיכרון. מעבירים לפונקציה הזאת גודל זיכרון מבוקש (בבתים), והיא מחזירה מצביע לאזור בגודל הזה שהוקצה בזיכרון. הקצאת זיכרון בזמן הריצה נקראת "הקצאה דינאמית". הקצאת זיכרון בזמן הריצה נקראת "הקצאה דינאמית".

הקצאת זיכרון דינאמית – דוגמא int main() int main() { int num, *a; int num, *a; scanf(“%d”, &num); scanf(“%d”, &num); a = (int *) malloc (num * sizeof(int) ) ; a = (int *) malloc (num * sizeof(int) ) ; } המשמעות היא: תקצה בזיכרון מקום רצוף בגודל num משתנים מסוג int, ותחזיר את כתובת ההתחלה של המקום שהוקצה, כמצביע ל- int. ההקצאה מתבצעת בזמן ריצת התוכנית. המשמעות היא: תקצה בזיכרון מקום רצוף בגודל num משתנים מסוג int, ותחזיר את כתובת ההתחלה של המקום שהוקצה, כמצביע ל- int. ההקצאה מתבצעת בזמן ריצת התוכנית. הפונקציה sizeof מחזירה גודל בבתים של משתנה או טיפוס משתנה (int דורש בדרך-כלל 4 בתים). הפונקציה sizeof מחזירה גודל בבתים של משתנה או טיפוס משתנה (int דורש בדרך-כלל 4 בתים). לתוך a תיכנס הכתובת של השטח שהוקצה בזיכרון. לתוך a תיכנס הכתובת של השטח שהוקצה בזיכרון.

הקצאת זיכרון דינאמית - פורמלית המצביע = (סוג המצביע) malloc (מס' תאים * גודל תא) ; המצביע = (סוג המצביע) malloc (מס' תאים * גודל תא) ;למשל: a = (int * ) malloc (10 * sizeof(int) ) ; a = (int * ) malloc (10 * sizeof(int) ) ; ה- casting לסוג המצביע המתאים (במקרה הזה int *) נדרש כיוון שהפונקציה מחזירה כתובת של רצף בתים שטיפוסו לא מוגדר (void *). ה- casting לסוג המצביע המתאים (במקרה הזה int *) נדרש כיוון שהפונקציה מחזירה כתובת של רצף בתים שטיפוסו לא מוגדר (void *). צריך להעביר את זה לטיפוס המתאים כדי לוודא שניגש נכון לערכים שנמצאים שם (בהתאם לגודל המשתנה). צריך להעביר את זה לטיפוס המתאים כדי לוודא שניגש נכון לערכים שנמצאים שם (בהתאם לגודל המשתנה). נוכל לגשת לתאי המערך כמו שניגשים אל מערך רגיל, וגם לבצע חשבון עם המצביע הזה (למשל לגשת לכתובת ההתחלה ועוד 1). נוכל לגשת לתאי המערך כמו שניגשים אל מערך רגיל, וגם לבצע חשבון עם המצביע הזה (למשל לגשת לכתובת ההתחלה ועוד 1).

דוגמא: הקצאת מערך בגודל משתנה int main() { int *a, size,i; printf(“Enter array size\n”); scanf(“%d”, &size); a = (int *) malloc (size * sizeof(int)); for (i=0; i<size; i++) scanf(“%d”, &a[i]); for (i=0; i<size; i++) printf(“%d”, a[i]); return 0; } קולטים את הגודל הדרוש מקצים מקום עכשיו אפשר למשל לקלוט ערכים ולהדפיס אותם, כמו במערך רגיל (אבל שימו לב ש- a הוא מצביע ולא מערך, לכן ניתן למשל לשנות את ערכו כך שהוא יצביע אחר-כך למקום אחר)

הקצאת זיכרון דינאמית אם בקשת הקצאת הזיכרון נכשלת, כלומר אין מספיק זיכרון להקצאה שביקשנו, אז הפונקציה malloc מחזירה NULL. אם בקשת הקצאת הזיכרון נכשלת, כלומר אין מספיק זיכרון להקצאה שביקשנו, אז הפונקציה malloc מחזירה NULL. NULL הוא כזכור קבוע שערכו 0 שמוגדר בספריה stdlib.h. NULL הוא כזכור קבוע שערכו 0 שמוגדר בספריה stdlib.h. אחרי כל בקשת הקצאה אנחנו צריכים לוודא שאכן הזיכרון שביקשנו התקבל. למשל: אחרי כל בקשת הקצאה אנחנו צריכים לוודא שאכן הזיכרון שביקשנו התקבל. למשל: int *a; int *a; a = (int *) malloc (1000 * sizeof(int)); a = (int *) malloc (1000 * sizeof(int)); if (a==NULL) if (a==NULL) { printf(“Out of memory\n”); printf(“Out of memory\n”); exit(1); exit(1); }

הקצאת זיכרון דינאמית כל פונקציות ההקצאה הדינאמית נמצאות בספריה stdlib.h כל פונקציות ההקצאה הדינאמית נמצאות בספריה stdlib.h void *malloc(unsigned int size); void *malloc(unsigned int size); מקצה size בתים. כאמור, קריאה מוצלחת תחזיר את כתובת תחילת הזיכרון המוקצה ואחרת יוחזר NULL. מקצה size בתים. כאמור, קריאה מוצלחת תחזיר את כתובת תחילת הזיכרון המוקצה ואחרת יוחזר NULL. פונקציה נוספת דומה מאוד: פונקציה נוספת דומה מאוד: void *calloc(unsigned int n, unsigned int size_el); void *calloc(unsigned int n, unsigned int size_el); מקצה מערך של n איברים, כל איבר בגודל size_el בתים, כל בית מאותחל לאפס. קריאה מוצלחת תחזיר את כתובת תחילת הזיכרון המוקצה ואחרת יוחזר NULL. דוגמת שימוש: ptr=(int *) calloc(10,sizeof(int)); דוגמת שימוש: ptr=(int *) calloc(10,sizeof(int));

הקצאת זיכרון דינאמית פונקציה שימושית נוספת: פונקציה שימושית נוספת: void *realloc(void *ptr, unsigned int size); void *realloc(void *ptr, unsigned int size); מקבלת מצביע לשטח בזיכרון שהוקצה דינאמית (אותו מצביע שמחזירות malloc/calloc), ומספר בתים size (שהוא הגודל החדש הדרוש). מקבלת מצביע לשטח בזיכרון שהוקצה דינאמית (אותו מצביע שמחזירות malloc/calloc), ומספר בתים size (שהוא הגודל החדש הדרוש). הפונקציה משנה את גודל ההקצאה בהתאם לדרישה החדשה. אם הדרישה הייתה להגדיל את ההקצאה ואין אפשרות להגדיל את השטח הנוכחי, מוקצה שטח חליפי במקום אחר, והמידע מועתק לשם. הפונקציה משנה את גודל ההקצאה בהתאם לדרישה החדשה. אם הדרישה הייתה להגדיל את ההקצאה ואין אפשרות להגדיל את השטח הנוכחי, מוקצה שטח חליפי במקום אחר, והמידע מועתק לשם. קריאה מוצלחת תחזיר את כתובת תחילת הזיכרון המוקצה (שלא בהכרח השתנתה) ואחרת יוחזר NULL. קריאה מוצלחת תחזיר את כתובת תחילת הזיכרון המוקצה (שלא בהכרח השתנתה) ואחרת יוחזר NULL.

הדגמת קטע תוכנית עם realloc int * a; int size, new_size; int size, new_size; scanf(“%d”, &size); scanf(“%d”, &size); a = (int *) malloc ( size * sizeof(int) ) ; ……... ……... …….. …….. scanf(“%d”, &new_size); scanf(“%d”, &new_size); a= (int *) realloc(a, new_size * sizeof(int) ); a= (int *) realloc(a, new_size * sizeof(int) ); ……… ………

שחרור זיכרון שהוקצה דינאמית כזכור, אמרנו בעבר שמשתנים שמוגדרים בתוך פונקציה נעלמים אוטומטית עם סיומה. זה נכון רק לגבי משתנים שמוגדרים סטטית. כזכור, אמרנו בעבר שמשתנים שמוגדרים בתוך פונקציה נעלמים אוטומטית עם סיומה. זה נכון רק לגבי משתנים שמוגדרים סטטית. משתנים שמוקצים דינאמית לא נעלמים עם סיום הפונקציה. משתנים שמוקצים דינאמית לא נעלמים עם סיום הפונקציה. באחריותנו לשחרר את ההקצאה הזאת כשנסיים להשתמש בה, כפי שנסביר בשקפים הבאים. באחריותנו לשחרר את ההקצאה הזאת כשנסיים להשתמש בה, כפי שנסביר בשקפים הבאים. int main() int main() {.. f(); f();. } void f() { int *x; x = (int *)malloc(10 * sizeof(int)); …. }

שחרור זיכרון שהוקצה דינאמית אם אנחנו לא רוצים להמשיך להשתמש בזיכרון שהקצנו דינאמית בפונקציה, אנחנו צריכים לשחרר את הזיכרון הזה בפונקציה באופן מפורש, באמצעות פקודת free (שתודגם בהמשך). אם אנחנו לא רוצים להמשיך להשתמש בזיכרון שהקצנו דינאמית בפונקציה, אנחנו צריכים לשחרר את הזיכרון הזה בפונקציה באופן מפורש, באמצעות פקודת free (שתודגם בהמשך). אם אנחנו רוצים להמשיך להשתמש בזיכרון שהקצנו דינאמית בתוך פונקציה אחרי שהיא מסתיימת, אז היא צריכה להעביר את הכתובת של הזיכרון שהיא הקצתה למי שקרא לה (אחרת לא נדע איך לגשת לשם). אם אנחנו רוצים להמשיך להשתמש בזיכרון שהקצנו דינאמית בתוך פונקציה אחרי שהיא מסתיימת, אז היא צריכה להעביר את הכתובת של הזיכרון שהיא הקצתה למי שקרא לה (אחרת לא נדע איך לגשת לשם). בכל מקרה, כשנסיים להשתמש בזיכרון הזה נצטרך לשחרר אותו. בכל מקרה, כשנסיים להשתמש בזיכרון הזה נצטרך לשחרר אותו.

שחרור זיכרון שהוקצה דינאמית נשים לב: אם לא נשחרר זיכרון שהקצנו וסיימנו להשתמש בו, אז אנחנו עלולים למלא את זיכרון המחשב באיזורים שלכאורה תפוסים אבל בעצם לא נגישים, מה שנקרא "דליפת זיכרון" (עלול להיגמר לנו הזיכרון בגלל זה). נשים לב: אם לא נשחרר זיכרון שהקצנו וסיימנו להשתמש בו, אז אנחנו עלולים למלא את זיכרון המחשב באיזורים שלכאורה תפוסים אבל בעצם לא נגישים, מה שנקרא "דליפת זיכרון" (עלול להיגמר לנו הזיכרון בגלל זה). בכל מקרה עד סוף התוכנית צריך לשחרר כל מה שהקצינו דינאמית. בכל מקרה עד סוף התוכנית צריך לשחרר כל מה שהקצינו דינאמית.

שחרור זיכרון שהוקצה דינאמית הפונקציה free, שנמצאת בספריה stdlib.h, מקבלת מצביע ומשחררת את הזיכרון שהוא מצביע אליו. הגדרתה היא:הפונקציה free, שנמצאת בספריה stdlib.h, מקבלת מצביע ומשחררת את הזיכרון שהוא מצביע אליו. הגדרתה היא: void free(void *ptr) השימוש פשוט ע"י free(x);השימוש פשוט ע"י free(x); המצביע שמועבר ל-free חייב להכיל כתובת-התחלה של זיכרון שהוקצה דינאמית לפני כן (כלומר כתובת שהוחזרה ע"י malloc או calloc או realloc), ואז ההקצאה הזאת מבוטלת.המצביע שמועבר ל-free חייב להכיל כתובת-התחלה של זיכרון שהוקצה דינאמית לפני כן (כלומר כתובת שהוחזרה ע"י malloc או calloc או realloc), ואז ההקצאה הזאת מבוטלת. אם ננסה לשחרר משהו אחר, למשל החל מהמקום השני שהקצינו, או כתובת של משתנה שלא הוקצה דינאמית, אז התוכנית "תעוף".אם ננסה לשחרר משהו אחר, למשל החל מהמקום השני שהקצינו, או כתובת של משתנה שלא הוקצה דינאמית, אז התוכנית "תעוף". לגבי פקודת realloc: אם היא מקצה שטח חדש אז היא משחררת בעצמה את השטח הישן (צריך לשחרר בעצמנו רק את השטח החדש).לגבי פקודת realloc: אם היא מקצה שטח חדש אז היא משחררת בעצמה את השטח הישן (צריך לשחרר בעצמנו רק את השטח החדש).

שחרור זיכרון שהוקצה דינאמית - הדגמה void f() { int *x; x = (int *) malloc(10 * sizeof(int)); …. free(x); }

החזרת זיכרון שהוקצה דינאמית - הדגמה int *f() { int *x; x = (int *) malloc(10 * sizeof(int)); …. return x; }

החזרת זיכרון שהוקצה דינאמית - הדגמה int * allocate_int_array(int size) { int *ptr; ptr = (int *) malloc(size * sizeof(int)); if (ptr==NULL) { printf(“Out of memory”); exit(1); } return ptr; } הפונקציה מקצה דינאמית מערך של מס' שלמים בגודל המבוקש, בודקת שההקצאה הצליחה, ומחזירה את כתובת המערך שהוקצה. אפשר להחזיר את כתובת המערך הזה, שלא משוחרר בסוף הפונקציה כי הוא הוקצה דינאמית, אבל מי שקרא לפונקציה צריך לדאוג לשחררו בסיום השימוש בו.

נקודה לתשומת-לב: מצביעים לא מאותחלים חשוב לזכור, שכמו כל משתנה גם מצביעים אינם מאותחלים בהגדרה שלהם, וצריך לתת להם ערך.חשוב לזכור, שכמו כל משתנה גם מצביעים אינם מאותחלים בהגדרה שלהם, וצריך לתת להם ערך. אם ננסה לגשת לכתובת שנמצאת במצביע בלי שנתנו לו ערך התחלתי, התוכנית "תעוף". למשל:אם ננסה לגשת לכתובת שנמצאת במצביע בלי שנתנו לו ערך התחלתי, התוכנית "תעוף". למשל: int *p; *p=10; אפשר לגשת לכתובת שנמצאת במצביע רק אם שמנו בו קודם כתובת של משתנה או של שטח שהוקצה דינאמית. למשל: אפשר לגשת לכתובת שנמצאת במצביע רק אם שמנו בו קודם כתובת של משתנה או של שטח שהוקצה דינאמית. למשל: int i; p=&i;או: p=(int *) malloc (5*sizeof(int)); הכתובת ב- p לא אותחלה

נקודה לתשומת-לב: מצביעים לא מאותחלים כזכור, אפשרות נוספת שראינו למתן ערך למצביע היא ע"י הכנסת כתובת של מערך או של מצביע אחר אליו.כזכור, אפשרות נוספת שראינו למתן ערך למצביע היא ע"י הכנסת כתובת של מערך או של מצביע אחר אליו. int a[10]; p=a;

עוד נקודה לתשומת-לב: מחרוזת קבועה אם נכניס מחרוזת קבועה למצביע על char בלי לאתחל אותו (לא מחרוזת מהקלט) אז לא תיקרה תעופה, אפילו שלא בוצעה הקצאה כלשהי ואפילו שלא ניתן להעתיק מחרוזות על-ידי השמה.אם נכניס מחרוזת קבועה למצביע על char בלי לאתחל אותו (לא מחרוזת מהקלט) אז לא תיקרה תעופה, אפילו שלא בוצעה הקצאה כלשהי ואפילו שלא ניתן להעתיק מחרוזות על-ידי השמה. זה כיוון שזאת השמה של כתובות: הקומפיילר שומר בזיכרון כל מחרוזת קבועה שהוא מוצא בתוכנית, ולכן למחרוזת הזאת כבר יש איזשהי כתובת בזיכרון שבה היא מאוחסנת. המצביע רק מצביע לשם.זה כיוון שזאת השמה של כתובות: הקומפיילר שומר בזיכרון כל מחרוזת קבועה שהוא מוצא בתוכנית, ולכן למחרוזת הזאת כבר יש איזשהי כתובת בזיכרון שבה היא מאוחסנת. המצביע רק מצביע לשם. למשל אפשר לכתוב: למשל אפשר לכתוב: char *pc, *ps; pc=“Hello!”;ps=“Hello!”; קומפיילרים סטנדרטיים לא יאפשרו לשנות מחרוזת קבועה כזו (כי שינוי ישפיע על כל הופעותיה בתוכנית). קומפיילרים סטנדרטיים לא יאפשרו לשנות מחרוזת קבועה כזו (כי שינוי ישפיע על כל הופעותיה בתוכנית).‘H’‘e’‘l’‘l’‘o’‘!’‘\0’ps pc

הקצאת זיכרון דינאמית - סיכום אפשר להקצות מקום בזיכרון בזמן הריצה. בפרט, אפשר ליצור מערך בגודל שתלוי בקלט (גודל שלא ידוע מראש). אפשר להקצות מקום בזיכרון בזמן הריצה. בפרט, אפשר ליצור מערך בגודל שתלוי בקלט (גודל שלא ידוע מראש). בספריה stdlib.h נמצאות הפקודות malloc, calloc, realloc, free. בספריה stdlib.h נמצאות הפקודות malloc, calloc, realloc, free. כשמקצים מקום בזיכרון מוחזרת הכתובת שלו, ונשמור אותה במצביע (בהתאם לסוג המשתנה שנירצה לשמור במקום הזה). אי-אפשר לתת שם למשתנה/מערך החדש, אבל אפשר לגשת אליהם דרך המצביע. כשמקצים מקום בזיכרון מוחזרת הכתובת שלו, ונשמור אותה במצביע (בהתאם לסוג המשתנה שנירצה לשמור במקום הזה). אי-אפשר לתת שם למשתנה/מערך החדש, אבל אפשר לגשת אליהם דרך המצביע. צריך לזכור לשחרר מה שהקצינו כשמסיימים להשתמש בזה. צריך לזכור לשחרר מה שהקצינו כשמסיימים להשתמש בזה. כתיבה לכתובת שנמצאת במצביע לא מאותחל תגרום לתעופה – צריך לזכור לאתחל אותו. כתיבה לכתובת שנמצאת במצביע לא מאותחל תגרום לתעופה – צריך לזכור לאתחל אותו.