Menu
Coddy logo textTech

מה זה קומפיילר (מהדר)?

קומפיילר (compiler, מהדר) הוא תוכנית שמתרגמת קוד מקור שנכתב בשפת תכנות לקוד מכונה, או לצורה נמוכה אחרת כמו bytecode, לפני שהתוכנית רצה. התוכנית המתורגמת יכולה לרוץ אחר כך בלי קוד המקור המקורי.

מאת Kevin Spektor, מייסד שותף ו-CTO

עודכן ב-24 בספטמבר 2026

קוד מקור
  1. 1print("Hello")
  2. 2total = 2 + 3
  3. 3print(total)
  4. 4print("Done")
פלט
מספר קומפילציות0
הרצות0

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

שמרו את תוכנית ה-C הזו בשם hello.c:

#include <stdio.h>

int main(void) {
    int price = 4;
    printf("Total: %d\n", price * 3);
    return 0;
}

אחר כך הקלידו gcc hello.c -o hello. לרגע לא קורה שום דבר גלוי, ואז מופיע ליד קוד המקור קובץ חדש בשם hello. הקובץ הזה הוא הפלט של הקומפיילר: קוד מכונה שהמעבד שלכם יכול להריץ. מחקו את hello.c ו-./hello עדיין עובד, כי כל מה שהתוכנית צריכה כבר תורגם.

gcc hello.c -o hello
./hello
Total: 12

איך קומפיילר עובד, שלב אחרי שלב

קומפיילר קורא קוד מקור כטקסט פשוט ועובר עליו בשלבים. ניקח את השורה היחידה total = price * 3:

  1. ניתוח לקסיקלי. הטקסט מתפרק לטוקנים, ה"מילים" של השפה: השם total, האופרטור =, השם price, האופרטור *, המספר 3. רווחים והערות נזרקים כאן.
  2. ניתוח תחבירי (parsing). הטוקנים מסודרים בעץ תחביר שמתעד את המבנה: השמה שהערך שלה הוא מכפלה של price ו-3. קוד ששובר את הדקדוק של השפה נעצר כאן עם שגיאת תחביר.
  3. ניתוח סמנטי. הקומפיילר בודק משמעות: האם הוכרז על price, האם הטיפוסים מתאימים, האם הפונקציה שנקראת קיימת.
  4. אופטימיזציה. התוכנית נכתבת מחדש כך שתרוץ מהר יותר או תשתמש בפחות זיכרון, בלי לשנות את מה שהיא עושה. x * 2 יכול להפוך להוראת הזזה אחת, וקוד שלעולם לא ירוץ מוסר.
  5. יצירת קוד. הקומפיילר כותב את הפלט עבור יעד: קוד מכונה של x86-64 או ARM, או bytecode למכונה וירטואלית.

ב-C וב-C++ יש שלב אחרון, קישור (linking), שמחבר את הקבצים המקומפלים שלכם עם קוד מספריות (כמו printf מהספרייה הסטנדרטית של C) לקובץ הרצה אחד. gcc מריץ את ה-linker בשבילכם, ולכן זה מרגיש כמו פקודה אחת.

Python מגיעה עם שני השלבים הראשונים כמודולים סטנדרטיים, כך שאפשר לראות אותם עובדים על קלט אמיתי:

NAME 'total'
OP '='
NAME 'price'
OP '*'
NUMBER '3'
Assign(
  targets=[
    Name(id='total', ctx=Store())],
  value=BinOp(
    left=Name(id='price', ctx=Load()),
    op=Mult(),
    right=Constant(value=3)))

העץ הזה הוא מה ששאר הקומפיילר עובד ממנו. כבר לא אכפת לו מרווחים או משורות חדשות, רק מהמבנה: להשים ל-total את התוצאה של הכפלת price ב-3.

זמן קומפילציה: שגיאות שנמצאות לפני שהתוכנית רצה

מכיוון שקומפיילר קורא את כל התוכנית לפני שחלק כלשהו ממנה רץ, הוא יכול לדחות טעויות מוקדם. בדוגמה הזו אף אחת משלוש שורות ה-print שבתוך source לא רצה, אפילו לא הראשונה, כי הקומפיילר של Python דוחה את הטקסט לפני שההרצה מתחילה:

Rejected before running anything:
  '(' was never closed (line 3)

קומפיילרים לשפות עם טיפוסים סטטיים תופסים יותר מתחביר. השורה הזו ב-C, בקובץ בשם bad.c, נכונה מבחינה דקדוקית, אבל היא שומרת טקסט במשתנה מסוג מספר שלם:

int count = "five";

GCC 14 ומעלה עוצרים עם שגיאה:

bad.c:4:17: error: initialization of 'int' from 'char *' makes integer from pointer without a cast [-Wint-conversion]

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

דוגמאות לקומפיילרים

קומפיילרקוראמייצר
GCC, ClangC, C++קוד מכונה ל-x86-64, ARM ועוד
MSVC (Microsoft Visual C++)C, C++קובצי הרצה של Windows (.exe, .dll)
javacJavabytecode של ה-JVM (קובצי .class)
rustcRustקוד מכונה
go buildGoקובץ הרצה יחיד
tscTypeScriptJavaScript

שתי שורות מראות ש"קוד מכונה" הוא לא הפלט האפשרי היחיד. javac מייצר bytecode שה-Java Virtual Machine מריצה, חלק מסביבת הריצה של Java. tsc הופך TypeScript ל-JavaScript, שפה עילית אחרת; קומפיילר שעושה את זה נקרא לעתים קרובות transpiler.

קוד מכונה מקומפל קשור למשפחת מעבדים אחת ולמערכת הפעלה אחת. תוכנית שקומפלה ל-Windows על x86-64 לא רצה על Mac עם שבב Apple מסדרת M; מקמפלים את אותו קוד מקור מחדש לכל יעד.

קומפיילר או interpreter

Interpreter (מפרש) מריץ קוד מקור ישירות במקום לייצר קובץ תוכנית נפרד, וכך בדרך כלל מריצים Python ו-Ruby. רוב הכלים המודרניים של שפות משתמשים בשני הרעיונות: CPython מקמפל את הקובץ שלכם ל-bytecode ואז מפרש אותו, וה-JVM ומנוע V8 של JavaScript מקמפלים קוד שרץ לעתים קרובות לקוד מכונה בזמן שהתוכנית רצה. הטבלה המלאה זה לצד זה נמצאת בעמוד קומפיילר מול interpreter.

תפיסות שגויות נפוצות

  • "אם זה עובר קומפילציה, זה עובד." קומפיילר בודק שהתוכנית תקינה, לא שהיא נכונה. טעויות לוגיות וכשלים בזמן ריצה, כמו חלוקה באפס, עוברים.
  • "Python לא מקומפלת." CPython מקמפל כל קובץ ל-bytecode לפני שהוא מריץ אותו. קובצי ה-.pyc בתיקיות __pycache__ הם ה-bytecode הזה, שנשמר עבור המודולים שהתוכנית שלכם מייבאת, כדי שההרצה הבאה תוכל לדלג על השלב.
  • "קומפיילר אונליין הוא קומפיילר." אתרים שמריצים את הקוד שלכם בדפדפן שולחים אותו לשרת שמריץ את כל שרשרת הכלים (קומפיילר, linker והתוכנית עצמה) ומחזיר את הפלט. הקומפיילר הוא רק חלק אחד מזה.
  • "קוד מקומפל רץ בכל מקום." הוא רץ על המעבד ומערכת ההפעלה שהוא נבנה עבורם. ניידות מגיעה מקומפילציה מחדש, או ממכונה וירטואלית כמו ה-JVM.

לאן ממשיכים מכאן

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

שאלות נפוצות

מה הרכיבים של קומפיילר?
בדרך כלל מתארים קומפיילר בשלושה חלקים. החזית (front end) קוראת את קוד המקור, מפרקת אותו לטוקנים, מנתחת אותו לעץ תחביר ובודקת טיפוסים. החלק האמצעי (middle end) מבצע אופטימיזציה לצורת ביניים של התוכנית, והחלק האחורי (back end) מייצר קוד מכונה או bytecode למעבד היעד.
איך קומפיילר יכול לקמפל את עצמו?
בעזרת bootstrapping. הגרסה הראשונה של קומפיילר נכתבת בשפה קיימת, או מקומפלת בידי קומפיילר ישן יותר, ואז משמשת לקמפל את הגרסה הבאה, שכתובה כבר בשפה החדשה עצמה. GCC, למשל, כתוב בעיקר ב-C וב-C++ ונבנה עם קומפיילר C++ קיים, לעתים קרובות GCC מוקדם יותר.
מה ההבדל בין קומפיילר ל-assembler?
קומפיילר מתרגם שפה עילית כמו C או Rust, שבה שורה אחת יכולה להפוך להרבה הוראות מכונה. Assembler מתרגם שפת סף (assembly), שבה כל שורה מתאימה כמעט אחד לאחד להוראת מכונה בודדת. קומפיילרים כמו GCC מייצרים לעתים קרובות assembly קודם ומעבירים אותו ל-assembler.
מה זה קומפיילר JIT?
קומפיילר just-in-time (JIT) מתרגם קוד לקוד מכונה בזמן שהתוכנית רצה, ולא לפני כן. הוא עוקב אחרי החלקים שרצים הכי הרבה ומקמפל אותם, כך שתוכנית שרצה זמן רב נעשית מהירה יותר תוך כדי. ה-JVM, מנוע V8 של JavaScript ו-PyPy משתמשים כולם בקומפילציית JIT.
צריך להתקין קומפיילר כדי ללמוד לתכנת?
לא בהתחלה. עורכים בדפדפן ועורכי קוד אונליין מריצים את הקומפיילר או את ה-interpreter בשבילכם על שרת. כשעוברים למחשב שלכם, C ו-C++ צריכות קומפיילר כמו GCC או Clang, Java צריכה JDK, ו-Python צריכה את ה-interpreter של Python.
איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל