c programming tutorial - בקלות C++
מדריכי תכנות

שיעור 6: הקדמה למצביעים

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

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

מבנה מצביעים יכול גם הוא להיות מבלבל, כיוון שמצביעים יכולים גם לתת את מיקום הזיכרון וגם לתת את הערך שממוקם באותו מיקום. כאשר מצהירים על מצביע, המבנה הוא זה: ;שם* טיפוס_המשתנה . שים לב ל *. זהו המפתח להצהרה על מצביע, אם משתמשים בזה לפני שם המשתנה, זה יגדיר את המשתנה כמצביע.

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

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

לדוגמא:

#include <iostream.h>

int main()
{ 
 int x;              //A normal integer 
 int *pointer;    //A pointer to an integer 
 pointer=&x;      //Read it, "pointer equals the address of x"
 cin>>x;          //Reads in x    
 cout<<*pointer; 
	//Note the use of the * to output the actual number stored in x

 return 0;

}  

ה cout מוציא כפלט את הערך שבתוך x. למה זה כך? ובכן, התבונן בקוד. המספר השלם נקרא x. לאחר מכן מצביע למספר השלם מוגדר כ "pointer". ואז התוכנית מאחסנת את מיקום הזיכרון של של x ב pointer באמצעות שימוש בסימן האמפרסנד (&). אם אתה רוצה, אתה יכול לחשוב על זה כאילו שלצנצנת שהכילה את המספר השלם היה אמפרסנד בתוכה ואז הוא היה מוציא כפלט את השם שלה (במצביעים, את כתובת הזיכרון). לאחר מכן המשתמש מכניס כקלט את הערך עבור x. ואז ה cout משתמש ב * כדי לשים את הערך שמאוחסן במיקום הזיכרון של pointer. אם לצנצנת שמכילה את השם של הצנצנת השניה היה * לפניה היא הייתה נותנת את הערך שמאוחסן בצנצנת עם אותו שם כמו זה שבצנצנת עם השם. זה לא כל כך פשוט, ה * נותנת את הערך שבמיקום. הצורה ללא הכוכבית נותנת את מיקום הזיכרון.

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

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

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

דוגמא:

int *ptr = new int;

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

אופרטור ה delete משחרר את הזיכרון שהוקצה באמצעות new. כדי לעשות זאת, המבנה הוא כמו בדוגמא:

דוגמא:

delete ptr;

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

המשמעות האחרונה של NULL היא שאם אין יותר זיכרון פנוי, אפשר ש ptr לאחר שנעשה לו new יצביע ל NULL. לכן, זה הרגל טוב בתכנות לבדוק כדי לוודא שהמצביע מצביע למשהו לפני שמשתמשים בו. מובן מאליו שלא סביר שהתוכנית תעבוד ללא בדיקה זו.




לדף הראשון

<< לדף הקודם

לדף הבא >>