Let's learn C
מערכים דינאמיים
למה אנו צריכים מערכים דינאמיים ?
הכרנו את המבנה מערך סטטי והבנו שהוא מאוד שימושי במקרה של קליטת מידע רב, אבל רק כאשר אנו יודעים כבר מראש מה
גודל המידע שלנו.
אבל מה קורה כאשר אנו צריכים להוסיף או להוריד מידע מהמערך שלנו ?
הבעיה שלנו עם מערך סטטי הוא שאנו יכולים לבזבז מקום או שאנו יכולים להקצות מעט מדי מקום ואז אנו לא יכולים להכיל יותר מידע , לשם כך יש לנו את המערכים הדינאמיים.
יצירת מערך דינאמי
השימוש של מערך דינאמי מתאפשר בעזרת שימוש במצביעים ומוצהר כך:
;type *name
כדי שניצור מערך דינאמי אנו צריכים מצביע ועליו נפעיל את אחת מהפקודות של הקצאת זיכרון דינאמי:
malloc או calloc
malloc & calloc
פקודות אלו שייכות לספריות בשם: stdlib.h ו malloc.h ואנו משתמשים בהם כך:
- ;dynamic_array = (type*)malloc(amount*(sizeof(type))
- ;dynamic_array = (type*)calloc(amount , sizeof(type))
הסבר:
- (*type) – אומר מאיזה סוג אנו ניצור את המערך הדינאמי שלנו.
- amount – מציין את כמות התאים שאנו רוצים במערך.
- sizeof(type) - מציין את הגודל של סוג המערך (הכוונה שאם אנו רוצים ליצור מערך דינאמי מסוג int אז אנו נרשום sizeof(int)).
ההבדל בין malloc ל calloc
- כאשר אנו יוצרים מערך דינאמי באמצעות calloc, כל הערכים במערך החדש שיצרנו מכילים את הערך 0.
- בניגוד לכך, כאשר אנו יוצרים מערך דינאמי באמצעות malloc כל הערכים במערך החדש מכילים ערכי זבל.
ההבדל בין מערך דינאמי ללא דינאמי
מערך דינאמי עובד כמו מערך רגיל מלבד העובדה שניתן לקבוע את גודלו בזמן ריצת התוכנית.
בנוסף לכך גישה לתאים במערך הדינאמי זהה לגישה לתאים של מערך רגיל.
במידה ואתם מרגישים חלשים בחלק זה, כדאי לחזור על הנושא של מערכים
שליחת מערך דינאמי לפונקציה
שליחת מערך דינאמי לפונקציה זהה לשליחת מערך רגיל.
שליחת מערך רגיל:
;name_of_function(array , amount)
לעומת זאת חותמת הפונקציה במערך דינאמי בפונקציה תהיה שונה משל מערך רגיל:
-
קבלת מערך רגיל:
;name_of_function(type* pointer_to_array , type amount) -
קבלת מערך דינאמי:
;name_of_functions(type **double_pointer_to_dynamic_array , type amount)
הכוונה לכך היא כדי שנוכל לבצע שינויים בכתובת זיכרון של מערך בתוך פונקציה עלינו ליצור חותמת פונקציה שמקבלת
שני כוכביות (שעליו עשינו נושא בנפרד מצביע כפול).
כאשר אנו רושמים בmain שלנו את הקוד אנו נשלח כתובת של המערך שלנו כלומר:
&arr
חשוב לציין!
()free
לפני שאנו קופצים לדוגמאות חשוב לזכור שזיכרון דינאמי לא משוחרר באופן אוטומטי מהזיכרון, ולכן זה התפקיד שלנו
כמתכנתים לשחרר אותו.
נעשה זאת בכך שבכל פונקציה שאנחנו מגדירים מערך דינאמי אנו נדאג לכך שבסוף התוכנית
זיכרון זה
ישוחרר.
נשחרר את המערך כך:
;free(the_name_of_the_array)
אנו ברגע שפקודה זו מתבצעת היא משחררת מהזיכרון את כל המערך (אי אפשר לשחרר רק חלק מסויים).
אם ננסה לשחרר פעמיים את אותו הזיכרון תקפוץ לנו הודעת שגיאה.
()assert
אחרי שאנו עושים calloc, malloc או realloc אנו נשתמש בפונקציה בשם assert שתפקידה הוא להודיע לנו אם המחשב הצליח
להגדיר בזיכרון את המערך עם הגודל המבוקש.
נשתמש בפונקציה זו בכך שאחרי שנשתמש ב calloc, malloc או realloc נרשום:
;assert(the_name_of_the_array)
כדי להשתמש ב assert נצטרך להוסיף בתחילת הקוד:
#include <assert.h>
דוגמה ליצירת מערך בגודל שהמשתמש רוצה:
שינוי הקצאה של מערך דינאמי בעזרת realloc
פונקציית realloc מאפשרת לנו להגדיל או להקטין את גודל המערך.
שימוש בפקודה זו יתבצע כך:
;array_name = (type*)realloc(array_name ,sizeof(type)*amount)
- array_name – מציין את המערך אותו אנו רוצים להקטין או להגדיל.
- sizeof(type) -במידה ואינכם לגמרי מבינים את הנושא עדיין כדאי לחזור לנושא sizeof.
- amount - הגודל החדש של המערך.
לדוגמא:
אם נקטין את גודל המערך מחמש לשלוש שני הערכים האחרונים שלנו הולכים לאיבוד.
כלומר, לא נוכל לגשת לשני תאים אלו בזיכרון.