Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Studies

Pass By Value

תמונת הזכרון

בשביל להבין מה הבעיה שאנחנו מנסים לפתור בכלל, נסתכל על הדוגמא הבאה:

#include <stdio.h>
void swap(int a, int b) {
    int tmp = a;
    a = b;
    b = tmp;
}
int main() {
    int a = 1;
    int b = 5;
    printf("before call to swap: a = %d, b = %d", a, b);
    swap(a, b);
    printf("after call to swap: a = %d, b = %d", a, b);
}

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

העברת ארגומנטים לפונקציות ומחסנית הקריאות

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

  1. לפני הקריאה לפונקציה swap, הקומפיילר מייצר פקודות לבניית ה-stack frame שלה - ספציפית, הוא מעתיק את הארגומנטים a ו-b מהפונקציה main לתוך ה-stack frame החדש.

  2. לפני תחילת ריצת הפונקציה swap, האיבר העליון ביותר בזכרון במחסנית הקריאות מכיל את המשתנים a ו-b של הפונקציה swap. מתחתיו בזכרון במחסנית הקריאות נמצא ה-stack frame של הפונקציה main, בו נמצאים במקום אחר לגמרי המשתנים a ו-b של הפונקציה main.

  3. בסיום הפונקציה swap, הקומפיילר מייצר פקודות לקיפול מחסנית הקריאות וחזרה ל-stack frame של הפונקציה main. המשתנים a ו-b שבאותו ה-stack frame לא השתנו בכלל!

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

הסיבה לכך, כפי שראינו בעבר, היא שבשפת C ארגומנטים עוברים לפונקציות ע״י הערך שלהם בלבד. מנגנון זה נקרא pass by value - מיד נראה דרך נוספת להעביר ארגומנטים לפונקציה שתאפשר לנו לבצע את המשימה שרצינו.