לדלג לתוכן

הרצאה: פונקציות, מודולים ו־Header Files

מבוא

עד עכשיו כתבנו את כל הקוד שלנו בקובץ אחד – main.c, והשתמשנו רק בפונקציה אחת – main.

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

תכנות נכון דורש חלוקה לפונקציות – כל פונקציה אחראית על פעולה אחת. בנוסף, נרצה לפצל את הקוד לקבצים שונים (מודולים) – כדי שיהיה ברור יותר, קריא יותר, ונוכל לשתף פונקציות בין קבצים.


למה פונקציות?

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

דוגמה בסיסית:

#include <stdio.h>

void say_hello() {
    printf("שלום עולם\n");
}

int main() {
    say_hello(); // קריאה לפונקציה
    return 0;
}

איך מגדירים פונקציה?

סוג_החזרה שם_הפונקציה(פרמטרים) {
    // גוף הפונקציה
}

דוגמה עם פרמטרים והחזרת ערך:

int add(int a, int b) {
    return a + b;
}

שימוש:

int result = add(3, 5); // result יהיה שווה ל-8

מודולריות – פיצול לקבצים

נגיד שיש לנו הרבה פונקציות של מתמטיקה. לא נרצה שכולן יהיו ב־main.c.
ניצור קובץ חדש: math_utils.c

// math_utils.c
int add(int a, int b) {
    return a + b;
}

int mult(int a, int b) {
    return a * b;
}

אבל איך main.c ידע על הפונקציות האלו?

בשביל זה יש header file!


Header Files – קבצי .h

הHeader (כמו "כותרת") – מכיל רק את ההצהרות של הפונקציות, בלי מימוש.

// math_utils.h
int add(int a, int b);
int mult(int a, int b);

ככה נגיד ל־main.c: "היי, יש פונקציות כאלו – תאמין לי, תוכל להשתמש בהן".

שימוש ב־main.c:

#include <stdio.h>
#include "math_utils.h" // שים לב: סוגריים כפולים לקובץ משלנו

int main() {
    int sum = add(3, 4);
    printf("3 + 4 = %d\n", sum);
    return 0;
}

איך לקמפל פרויקט עם כמה קבצים?

נניח שיש לנו:

  • main.c

  • math_utils.c

  • math_utils.h

כדי לקמפל, נכתוב את הפקודה הבאה:

gcc main.c math_utils.c -o program

או שנקמפל שלב אחרי שלב את קבצי האובייקט ואז נאחד אותם:

gcc -c main.c         # יוצר main.o
gcc -c math_utils.c   # יוצר math_utils.o
gcc main.o math_utils.o -o program

שימו לב, שכשאתם כותבים קובץ header, חשוב מאוד לשים בתחילת הקובץ header ובסופו 3 הוראות מסוימות:

#ifndef MATH_UTILS_H
#define MATH_UTILS_H

// ההגדרה של הפונקציות

#endif

למעשה, ההוראות האלו מוודאות שאם הקוד עשה פעמיים include לקובץ, הפונקציה לא תוגדר פעמיים.
פעולת הifndef (if not define) בודקת אם הסימבול "MATH_UTILS_H" לא מוגדר, אם זה לא מוגדר- אז היא לא מבצעת את הקוד שכתוב עד "endif" (כל ההגדרות של הפונקציות) ואם לא, אז הוא מגדיר באמצעות פעולת define את הסימבול- ואז מבצע את כל ההגדרות, כך שאם יעשו שוב include לקובץ, הסימבול כבר יוגדר (MATH_UTILS_H בדוגמה למעלה) ואז התנאי יתקיים והקוד לא יורץ (ההגדרות).