תיעוד C
מדריך עיון תמציתי ל-C, מבוסס דוגמאות. קוראים את המושג, רואים את הקוד, ואז מתרגלים אותו במסלול של Coddy.
להתחיל מסלול C מודרךGetting Started
- מה זה CC היא שפה מקומפלת, קטנה ומהירה משנת 1972 שעדיין מריצה מערכות הפעלה, מסדי נתונים וכמעט כל מכשיר משובץ. כאן תמצאו מה היא, איפה היא רצה ולמה שווה ללמוד אותה ב-2026.
- התקנת C (GCC)התקינו קומפיילר C עובד בכל מערכת: MinGW-w64 ב-Windows, clang של Apple ב-macOS ו-gcc ב-Linux, ובנוסף איך לוודא שההתקנה עבדה ולקמפל את הקובץ הראשון.
- קומפילציה והרצההפכו קובץ .c לתוכנית שרצה: הפקודה gcc, מה באמת עושים שלבי הקדם-עיבוד, הקומפילציה והקישור, הדגלים שכדאי להשתמש בהם מהיום הראשון, ואיך לקרוא את השגיאות כשמשהו נכשל.
- תחביר Cלכל תוכנית C יש אותו שלד: הכללות, פונקציית main, פקודות שמסתיימות בנקודה ופסיק, ובלוקים בסוגריים מסולסלים. הנה מה שכל חלק עושה, והכללים שהקומפיילר באמת אוכף.
- הערותל-C יש שני סגנונות הערות, // לשורה אחת ו-/* */ לכמה שורות, עם היסטוריה שונה ומלכודת קינון אחת. הנה איך להשתמש בשניהם, ומה שווה להעיר עליו ומה לא.
Variables & Types
- משתניםאיך מצהירים על משתנה ב-C, ההבדל בין הצהרה לאתחול, כללי מתן שמות, הצהרה על כמה משתנים בבת אחת, ולמה משתנה לא מאותחל הוא הבאג הנפוץ ביותר אצל מתחילים.
- טיפוסי נתוניםלכל משתנה ב-C יש טיפוס שקובע את הגודל שלו ומה הוא יכול להכיל. הנה כל הטיפוסים הבסיסיים, הגדלים האמיתיים שלהם, signed מול unsigned, sizeof, limits.h, ומה קורה בגלישה.
- קבועיםשלוש דרכים לתת שם לערך שלעולם לא משתנה ב-C: מילת המפתח const, מאקרו של #define וקבועי enum. מה כל אחד מהם הוא בפועל, ובמה לבחור ומתי.
- אופרטוריםכל אופרטור של C ששווה להכיר: אריתמטיים, השמה, השוואה, לוגיים והגדלה, ובנוסף המלכודת של חילוק שלמים, איך מודולו מתנהג עם מספרים שליליים וטבלת קדימויות שאפשר לסמוך עליה.
- ערכים בוליאנייםל-C לא היה טיפוס בוליאני עד C99. אפס הוא שקר, כל השאר אמת, השוואות מחזירות int, ו-stdbool.h מוסיף מעל זה את bool, true ו-false. ובנוסף, הבאג של = מול == שהעיצוב הזה מאפשר.
- המרת טיפוסיםC ממירה בין טיפוסים כל הזמן: לפעמים כי ביקשתם עם cast, ולעיתים קרובות יותר מעצמה. כאן תמצאו את כללי הקידום, את התחביר של cast מפורש, ואת ההמרות שמאבדות נתונים בשקט.
Control Flow
- if ו-elseאיך C מקבלת החלטות: פקודת if, else, שרשראות else if, קינון והאופרטור הטרנרי, ובנוסף כלל האמת (0 הוא שקר, כל השאר אמת) והבאג של `=` מול `==` ששובר תנאים בשקט.
- switchאיך משפט switch ב-C בוחר ענף אחד מתוך רשימת קבועים: תוויות case, למה break חשוב, fall-through מכוון ומקרי, default, switch על תווים ועל enums, ומתי switch עדיף על שרשרת else-if.
- לולאת forאיך חוזרים על קוד עם לולאת for ב-C: הכותרת בת שלושת החלקים, ספירה למעלה ולמטה, מעבר על מערכים עם טריק ה-sizeof, לולאות מקוננות, לולאות אינסופיות, והבאגים של טעות באחד ומשתנים unsigned שתופסים את כולם.
- לולאת whileאיך לולאת while ב-C חוזרת על עצמה עד שתנאי משתנה: כלל התנאי-קודם, לולאות עם ערך זקיף, קריאת קלט עד EOF, while(1) ומעבר בין for ל-while.
- לולאת do-whileהלולאה של C שהגוף שלה בא קודם: איך do-while מבטיחה סיבוב אחד לפני הבדיקה, למה היא מסתיימת בנקודה ופסיק, תבניות התפריט והניסיון החוזר שבשבילן היא נוצרה, ובמה היא שונה מלולאת while רגילה.
- break ו-continuebreak יוצאת מלולאה או מ-switch; continue מדלגת לסיבוב הבא. איך כל אחת מתנהגת ב-for, ב-while וב-do-while, איך יוצאים מלולאות מקוננות עם דגל או goto, והשימושים השגויים שהופכים לולאות לקשות למעקב.
Functions
- פונקציותאיך מגדירים וקוראים לפונקציות ב-C: טיפוס ההחזרה, פרמטרים, ערכים מוחזרים, פונקציות void, למה פירוק לחלקים חשוב, ודוגמה מלאה שבנויה מחלקים קטנים עם שמות.
- פרמטרים של פונקציותC מעבירה הכול by value: פונקציות מקבלות עותקים, אף פעם לא את המקור. מה זה אומר בפועל, איך מצביעים מדמים העברה by reference, למה מערכים מתנהגים אחרת, ואיך מחזירים כמה תוצאות.
- אבות טיפוס של פונקציותלמה C צריכה לראות את הצורה של פונקציה לפני שקוראים לה: כתיבת אבות טיפוס, תיקון שגיאות implicit declaration, אבות טיפוס בקובצי header, וההבדל האמיתי בין f(void) ל-f().
- רקורסיהאיך פונקציה ב-C קוראת לעצמה: תנאי העצירה שעוצר אותה, עצרת ופיבונאצ'י צעד אחר צעד, למה פיבונאצ'י הנאיבי איטי בצורה קטסטרופלית, מה זה באמת stack overflow, ומתי לולאה היא התשובה הטובה יותר.
- Scopeאיפה משתנה ב-C נראה וכמה זמן הוא חי: scope של בלוק, פרמטרים של פונקציה, משתנים גלובליים ב-scope של קובץ, משתנים מקומיים static ששורדים בין קריאות, פונקציות static, הסתרה (shadowing) ולמה משתנים גלובליים עושים צרות.
Pointers
- מצביעיםמצביע הוא משתנה ששומר כתובת זיכרון. העמוד בונה את הרעיון מהיסוד: האופרטורים & ו-*, הצהרה על מצביעים ו-dereference שלהם, למה טיפוסי מצביעים חשובים, והפונקציה swap() שמראה למה מצביעים קיימים בכלל.
- אריתמטיקה של מצביעיםהוספת 1 למצביע לא מוסיפה בית אחד: היא עוברת לאובייקט הבא מאותו טיפוס. העמוד מכסה את ptr+1, הגדלה והקטנה, הפרש בין מצביעים, השוואות, מעבר על מערך עם מצביע, והכלל של מקום אחד אחרי הסוף.
- מצביעים ומערכיםב-C שם של מערך הופך למצביע לאיבר הראשון שלו כמעט בכל מקום שבו משתמשים בו. העמוד מסביר את הדעיכה הזו, למה arr[i] הוא ממש *(arr+i), למה הגודל של מערך חייב לעבור בנפרד לפונקציות, ובמה מצביע למערך שונה ממערך של מצביעים.
- מצביעים לפונקציותגם לפונקציות יש כתובות, ומצביע לפונקציה שומר אחת כזו. העמוד מפענח את תחביר ההצהרה, מראה איך typedef הופך אותו לקריא, ומתקדם ל-callbacks, ל-qsort עם פונקציית השוואה משלכם ולטבלאות dispatch.
- מצביעי NULLNULL היא הכתובת שמצביע מחזיק כשהוא לא מצביע על כלום. העמוד מסביר מה NULL באמת, למה dereference שלו קורס, במה הוא שונה מ-0 וממצביע לא מאותחל, ואת הדפוסים ההגנתיים שמרחיקים באגי null מהקוד שלכם.
Arrays & Strings
- מערכיםאיך מצהירים על מערכים ב-C ומאתחלים אותם, מאנדקסים מאפס, מחשבים את האורך עם sizeof, עוברים על האיברים בלולאה, ולמה קריאה מעבר לסוף היא התנהגות לא מוגדרת ולא הודעת שגיאה.
- מערכים רב-ממדייםאיך מצהירים, מאתחלים ועוברים בלולאה על מערכים דו-ממדיים ב-C, מה פריסת row-major אומרת בפועל בזיכרון, למה העברת מערך דו-ממדי לפונקציה דורשת את מספר העמודות, ודוגמה מלאה עם מטריצה.
- מחרוזותל-C אין טיפוס מחרוזת: מחרוזת היא מערך של char שמסתיים בבית '\0'. העמוד הזה בונה את המודל המנטלי הזה, ואז עוסק בליטרלים, בהדפסה, במעבר על תווים, ולמה אי אפשר להעתיק מחרוזת עם =.
- פונקציות מחרוזותסיור מעשי ב-<string.h>: מדידה עם strlen, העתקה עם strcpy ו-strncpy, חיבור עם strcat, השוואה עם strcmp, חיפוש עם strchr ו-strstr, ואיך לקבוע גודל של buffers כך שאף אחת מהן לא תגלוש.
- המרת מחרוזותהמרה בין טקסט למספרים ב-C: למה atoi לא יכולה לדווח על שגיאה, איך משתמשים נכון ב-strtol וב-strtod עם endptr ו-errno, הפיכת מספרים למחרוזות עם snprintf, וטריקים לספרה בודדת עם '0'.
Dynamic Memory
- זיכרון דינמילמה ה-heap קיים, איך malloc נותנת לכם זיכרון שהגודל שלו נקבע בזמן ריצה, הניב p = malloc(n * sizeof *p), בדיקה מול NULL, שחרור פעם אחת בדיוק, ומערך דינמי מההתחלה ועד הסוף.
- calloc ו-realloccalloc נותנת זיכרון מאופס ומכפילה את הגודל בבטחה; realloc מגדילה בלוק שכבר מילאתם. העמוד הזה מכסה את שתיהן, את ניב המצביע הזמני שמונע מ-realloc שנכשלה לגרום לדליפה, ומתי calloc עדיפה על malloc ועוד memset.
- דליפות זיכרוןמה זו באמת דליפה, שלוש הדרכים שבהן תוכניות C מייצרות דליפות, משמעת הבעלות שמונעת אותן, ואיך מוצאים את השאר עם valgrind ועם הדגל -fsanitize=address, עם תוכנית דולפת שמתוקנת צעד אחר צעד בסוף.
- Stack מול Heapאיפה הנתונים שלכם באמת נמצאים: אחסון אוטומטי ב-stack, אחסון דינמי ב-heap, ואחסון סטטי כאזור השלישי. כולל באג המצביע התלוי הקלאסי שנוצר מהחזרת משתנה מקומי, וכלל לבחירה ביניהם.
Structs, Unions & Enums
- Structsאיך מקבצים ערכים קשורים לטיפוס אחד עם struct ב-C: הצהרה, גישה לשדות עם אופרטור הנקודה, designated initializers, מערכים של structs, קינון, וכלל ההעתקה בהעברה שמפתיע את כולם.
- Structs ומצביעיםאיך מצביעים על struct ב-C: אופרטור החץ, למה (*p).x צריך את הסוגריים שלו, העברת structs במצביע כדי לשנות אותם או לחסוך העתקות, הקצאת struct עם malloc ובניית צומת של רשימה מקושרת.
- typedefאיך typedef נותן שם חדש לטיפוס קיים ב-C: הניב typedef struct עם תגית ובלעדיה, typedef למצביעים לפונקציות ולמערכים, והמקרה היחיד שבו typedef מזיק: הסתרה של מצביע.
- Unionsאיך union ב-C שומר כמה טיפוסים באותם בתים: למה הגודל שלו הוא של האיבר הגדול ביותר, למה צריך לקרוא את האיבר שנכתב אחרון, ואיך tagged union (enum ועוד union) הופך אותו לבטוח.
- enumאיך מגדירים enum ב-C: מספור אוטומטי, ערכים מפורשים, שימוש ב-enum בתוך switch כדי שהקומפיילר יתפוס מקרים חסרים, המרת enum למחרוזת, ומוסכמות השמות ששומרות עליהם קריאים.
Input & Output
- printfאיך printf באמת עובדת ב-C: המודל של מחרוזת הפורמט, ה-specifiers שמשתמשים בהם כל יום, רוחב ודיוק לפלט מיושר, הדפסה הגיונית של float, הערך המוחזר, ולמה printf(user_input) היא פרצת אבטחה.
- scanfאיך קוראים קלט עם scanf ב-C: למה ה-& חובה, איך מטופלים רווחים, גלישת ה-buffer של %s והתיקון עם רוחב, בדיקת הערך המוחזר, באג ירידת השורה שנשארת, ו-fgets כחלופה החסינה.
- Format specifiersכל ה-format specifiers של C במקום אחד: מה אומרים %d, %s, %c, %f, %p וכל השאר, מגדירי האורך l, ll, h ו-z, רוחב, דיוק ודגלים, ואילו מהם שונים בין printf ל-scanf.
- עבודה עם קבציםאיך קוראים וכותבים קבצים ב-C: טבלת המצבים של fopen, בדיקה מול NULL, כתיבה עם fprintf ו-fputc, קריאה עם fgets, fscanf ו-fgetc, הלולאה הקלאסית של שורה אחר שורה, ומתי להשתמש במצב בינארי.
- ארגומנטים משורת הפקודהאיך תוכנית C קוראת את שורת הפקודה שלה: המבנה של argc ו-argv, מעבר על הארגומנטים, מה יש ב-argv[0], המרת מספרים עם strtol במקום atoi, ומחשבון קטן שמחבר את הכול.
The Preprocessor
- Preprocessorה-preprocessor עורך את טקסט קוד המקור שלכם עוד לפני שהקומפיילר רואה אותו: מדביק קבצי header, מחליף מאקרו ומפעיל או מכבה קטעי קוד. כאן תמצאו את כל משפחת ההנחיות ואיך לראות את הפלט שלו.
- מאקרומאקרו פשוטים ומאקרו עם פרמטרים עם #define: למה כל ארגומנט וכל הגוף צריכים סוגריים, המלכודת של הערכה כפולה, מאקרו מרובי שורות עם do-while(0), ומתי פונקציה או const הם הכלי הטוב יותר.
- קובצי headerאיך מפצלים תוכנית C לכמה קבצים: מה שייך ל-.h, מה שייך ל-.c, include guards שמונעים הכללה כפולה, קומפילציה של כמה קבצים יחד ושיתוף משתנים גלובליים עם extern.
- קומפילציה מותניתקמפלו קוד שונה לבניות שונות עם #ifdef, #ifndef, #if, #elif ו-#else: מתגי דיבאג, ענפים לפי פלטפורמה, הגדרת מאקרו משורת הפקודה עם -D, ושימוש ב-#if 0 כדי לנטרל קוד.
Standard Library
- פונקציות מתמטיותסיור ב-math.h: sqrt, pow, fabs, floor ו-ceil, round, fmod, משפחות הטריגונומטריה והלוגריתמים, INFINITY ו-NAN, ובנוסף דגל הקישור -lm שגורם לשגיאה הקלאסית undefined reference.
- מספרים אקראייםאיך מייצרים מספרים אקראיים ב-C עם rand() ו-RAND_MAX, למה מאתחלים עם srand(time(NULL)) פעם אחת בדיוק, מיפוי לטווח עם % וההטיה הקטנה שזה יוצר, מספרי double אקראיים ורצפים שחוזרים על עצמם.
- ספרייה סטנדרטיתמה כל header סטנדרטי נותן לכם: stdio.h, stdlib.h, string.h, math.h, time.h, ctype.h, limits.h, stdbool.h, stdint.h ו-assert.h, עם דוגמה קצרה ועובדת לכל אחד.
Errors & Debugging
- Segmentation Faultsegfault אומרת שהתוכנית שלכם נגעה בזיכרון שלא שייך לה. כאן תמצאו את חמשת הגורמים שאחראים כמעט לכולן, כל אחד עם דוגמה מינימלית והתיקון שלה, ואיך מוצאים את השורה המדויקת עם gdb ו-AddressSanitizer.
- שגיאות נפוצותהטעויות שכל מתכנת C עושה לפחות פעם אחת: נקודה ופסיק חסרה, = במקום ==, הצהרות מרומזות, scanf בלי &, השוואת מחרוזות עם ==, חילוק שלמים, משתנים לא מאותחלים וטעויות של אחד. כל אחת כתסמין, סיבה ותיקון.
- התנהגות לא מוגדרתהתנהגות לא מוגדרת היא קוד שתקן C לא מטיל עליו שום דרישה, ולכן הכול יכול לקרות, כולל אופטימייזר שמוחק את הבדיקות שכתבתם. כאן תמצאו מה גורם לה, למה "אצלי זה עובד" לא מוכיח כלום, ואילו דגלים תופסים אותה.