Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Studies

בייטים, ביטים והצגת משתנים

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

  1. היחידה הבסיסית ביותר נקראת ביט (bit), או סיבית בעברית. ביט יכול לקבל את הערכים 0 או 1 בלבד - ניתן לחשוב על ביטים כמו מתגים, הנמצאים במצב דלוק או כבוי. בתוכנה נייצג כל ביט כספרה במספר בינארי אחד.
  2. כל קבוצה של 8 ביטים נקראת בייט (byte), או בית בעברית. כשאנחנו אומרים למשל שלמחשב שלנו יש זכרון של 4 ג׳יגהבייט (4GB), אלו הבייטים עליהם מדברים.
  3. כל משתנה שנגדיר יתפוס בזכרון כמות מסוימת של בייטים - לדוגמא, משתנה char תופס בייט אחד, לעומת משתנה int שתופס 4 בייטים.
  4. ניתן לחשוב על הזכרון בתור שורה ארוכה וממוספרת של המון בייטים. המספור שמקבל כל בייט נקרא כתובת. לדוגמא, אם הבייט בכתובת 100 מכיל כרגע משתנה כלשהי int x, אנחנו אומרים שהכתובת של x בזכרון היא 100. בהמשך נעשה שימוש מקיף בנושא הכתובות של משתנים בזכרון. רוב המשתנים יתפסו יותר מבייט אחד בזכרון, ובמקרה זה אנחנו אומרים שהכתובת שלהם היא הכתובת של הבייט הראשון שהם נמצאים בו.
  5. הביטים שמרכיבים כל בייט נותנים לו ערך, וביחד כל משתנה מפורש לפי הבייטים שלו. ניקח משתנה int למשל שערכו 549:
int x = 549;

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

00000000 00000000 00000010 00100101

נסו להמיר בעצמכם את המספר בייט לאחר בייט לספרות דצימליות וראו שאתם מקבלים את התשובה הרצויה!

כלומר: כשאנו כותבים את שורת הקוד int x = 549, הקומפיילר שומר את הבייטים 00000000 00000000 00000010 00100101 במקום שהורנו לו. הבנה עמוקה של כיצד הזכרון נראה היא לא פחות מקריטית להמשך ולכן נשקיע מאמץ רב בבנייה עמוקה שלה.

שאלה: אמרנו שגודל משתנה int הוא 4 בייטים - כלומר, הערך המספרי של משתנה מסוג זה מיוצג ע״י 4 בייטים שהם 32 ביטים. בהתאמה, מהו הערך המקסימלי שמשתנה מסוג זה יכול לקבל?

כתובת של משתנה

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

#include <stdio.h>
int main() {
    int x = 5;
    char c = 'c';
    float f = -53.4;
    printf("x address = %p\n", &x);
    printf("c address = %p\n", &c);
    printf("f address = %p\n", &f);
}

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

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

Note

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

sizeof וגדלים של משתנים

השפה מעמידה לרשותנו אופרטור בשם sizeof, שמקבל טיפוס ומחזיר את הגודל שלו בבתים:


#include <stdio.h>
#include <stdbool.h>
int main() {
    printf("Size of char: %d bytes\n", sizeof(char));
    printf("Size of bool: %d bytes\n", sizeof(bool));
    printf("Size of int: %d bytes\n", sizeof(int));
    printf("Size of float: %d bytes\n", sizeof(float));
    printf("Size of double: %d bytes\n", sizeof(double));
}

Caution

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