ברוכים הבאים ליחידת המבוא לתכנות בשפת C, אבן יסוד בקורס "מעבדה בתכנות מערכות". יחידה זו תציג בפניכם את עקרונות הבסיס של שפת C, מבנה תוכנית פשוטה, תהליך הקומפילציה וההרצה, וכיצד לטפל בקלט ופלט בסיסי ובמשתנים וטיפוסי נתונים, שהם אבני הבניין של כל תוכנית.
מבנה תוכנית C בסיסית
כל תוכנית C מתחילה בפונקציה ראשית בשם main, שהיא נקודת הכניסה לתוכנית. לפני פונקציית main, נהוג לכלול קבצי כותרת (header files) המכילים הצהרות על פונקציות וקבועים שישמשו בתוכנית. קובץ הכותרת הנפוץ ביותר הוא <stdio.h>, המכיל פונקציות קלט/פלט סטנדרטיות.
דוגמה לתוכנית "Hello, World!":
#include <stdio.h> // כולל את ספריית הקלט/פלט הסטנדרטית
int main() { // פונקציית main - נקודת הכניסה לתוכנית
printf("Hello, World!\n"); // מדפיס את המחרוזת למסך
return 0; // מחזיר 0 כדי לציין שהתוכנית הסתיימה בהצלחה
}
נקודות מפתח במבנה:
#include <filename.h>: הוראה לקדם-מעבד לכלול קובץ כותרת.int main(): הגדרת הפונקציה הראשית.intמציין שהפונקציה מחזירה ערך שלם.{ }: סוגריים מסולסלים מגדירים בלוק קוד.;: נקודה-פסיק בסוף כל פקודה.return 0;: ערך החזרה של פונקצייתmainלמערכת ההפעלה, 0 מציין הצלחה.
קומפילציה והרצה (gcc)
שפת C היא שפה מהודרת (compiled language), כלומר, יש לתרגם את קוד המקור שכתבנו לשפת מכונה לפני שניתן יהיה להריץ אותו. תהליך זה נקרא קומפילציה, והוא מתבצע באמצעות מהדר (compiler). מהדר ה-gcc (GNU Compiler Collection) הוא מהדר נפוץ וחזק.
תהליך הקומפילציה:
- קדם-עיבוד (Preprocessing): קובץ המקור עובר עיבוד מקדים (לדוגמה, החלפת הוראות
#includeו-#define). - קומפילציה (Compilation): קוד המקור המתוקן מתורגם לקוד אסמבלי.
- הרכבה (Assembly): קוד האסמבלי מתורגם לקוד מכונה (קובץ אובייקט).
- קישור (Linking): קובצי האובייקט מקושרים יחד עם ספריות קוד (כמו
stdio.h) ליצירת קובץ הרצה (executable).
פקודות בסיסיות ב-gcc:
- קומפילציה והרצה:
gcc my_program.c -o my_program: מהדר את הקובץmy_program.cויוצר קובץ הרצה בשםmy_program../my_program: מריץ את קובץ ההרצה.
קלט/פלט בסיסי (printf, scanf)
אינטראקציה עם המשתמש היא חלק בלתי נפרד מרוב התוכניות. ב-C, פונקציות printf ו-scanf (הכלולות ב-<stdio.h>) הן הדרך הסטנדרטית לביצוע קלט ופלט.
printf - פלט למסך:
הפונקציה printf משמשת להדפסת נתונים למסך. היא מקבלת מחרוזת פורמט וארגומנטים נוספים בהתאם.
printf("Hello, %s! You are %d years old.\n", "Alice", 30);- מפרמטי פלט נפוצים:
%d(שלם),%f(עשרוני),%c(תו),%s(מחרוזת). - תווי בריחה (escape sequences):
\n(שורה חדשה),\t(טאב).
scanf - קלט מהמשתמש:
הפונקציה scanf משמשת לקליטת נתונים מהמשתמש. היא דורשת את כתובת הזיכרון של המשתנה כדי לאחסן בו את הקלט.
int age;printf("Enter your age: ");scanf("%d", &age);// שימו לב לסימן ה-& לפני age!
משתנים וטיפוסי נתונים
משתנים הם מקומות שמורים בזיכרון המחשב לאחסון נתונים. לכל משתנה יש שם, טיפוס נתונים וערך. טיפוס הנתונים קובע את סוג הערכים שהמשתנה יכול לאחסן ואת כמות הזיכרון המוקצית לו.
הצהרה ואתחול:
- הצהרה (Declaration): הגדרת שם המשתנה וטיפוסו. לדוגמה:
int count; - אתחול (Initialization): מתן ערך התחלתי למשתנה. לדוגמה:
count = 0;אוint count = 0;
טיפוסי נתונים בסיסיים:
int
מספרים שלמים (ללא נקודה עשרונית). גודלו תלוי ארכיטקטורה, לרוב 4 בתים. טווח: כ-±2 מיליארד.
char
תו בודד. גודלו בית אחד. משמש גם למספרים שלמים קטנים (0-255 או -128 עד 127). מיוצג על ידי ערך ASCII.
float
מספרים עשרוניים בנקודה צפה (דיוק יחיד). לרוב 4 בתים. משמש לערכים עם שבר עשרוני.
double
מספרים עשרוניים בנקודה צפה (דיוק כפול). לרוב 8 בתים. מציע דיוק רב יותר מ-float.
שאלות לדיון
- מהם השלבים העיקריים בתהליך הקומפילציה של תוכנית C באמצעות GCC? מדוע חשוב להבין תהליך זה?
- הסבר את ההבדל בין הצהרה על משתנה לאתחולו. תן דוגמה לכל אחד וציין מה עלול לקרות אם משתנה מוצהר אך לא מאותחל לפני השימוש בו.
- מתי נשתמש ב-
printfומתי ב-scanf? מהו התפקיד של סימן ה-&בפונקצייתscanf, ומדוע הוא כה קריטי? - אילו טיפוסי נתונים בסיסיים קיימים ב-C, ומתי נבחר להשתמש בכל אחד מהם? תאר מצב שבו בחירת טיפוס נתונים שגוי עלולה להוביל לבעיות.
נקודות לתשובת מודל
- תהליך הקומפילציה: קוד מקור עובר קדם-עיבוד, קומפילציה (לקוד אסמבלי), הרכבה (לקוד מכונה/אובייקט) וקישור (ליצירת קובץ הרצה). הבנת התהליך חיונית לפתרון בעיות (debugging) והבנת אופן פעולת התוכנה.
- הצהרה מול אתחול: הצהרה (לדוגמה:
int x;) מגדירה את שם המשתנה וטיפוסו. אתחול (לדוגמה:x = 10;אוint x = 10;) נותן למשתנה ערך התחלתי. שימוש במשתנה לא מאותחל עלול להוביל ל"ערך זבל" (garbage value) ולתוצאות בלתי צפויות. - printf/scanf:
printfמשמשת לפלט נתונים למסך, ואילוscanfמשמשת לקליטת קלט מהמשתמש. סימן ה-&ב-scanfמספק את כתובת הזיכרון של המשתנה, כך שהפונקציה תוכל לכתוב את הערך הנקלט ישירות למיקום זה בזיכרון. שכחתו תוביל לשגיאת ריצה. - טיפוסי נתונים:
int(שלמים),char(תווים/מספרים קטנים),float/double(מספרים עשרוניים בדיוק שונה). הבחירה תלויה בסוג הנתונים ובטווח הערכים הנדרש. לדוגמה, שימוש ב-charלאחסון מספר גדול מ-127 (signed) או 255 (unsigned) יוביל לגלישה (overflow) ולאובדן נתונים.