Menu
Coddy logo textTech

מצביע לעומת ערך

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C של Coddy. שיעור 9 מתוך 61.

כשמעבירים struct לפונקציה, C נותנת לך שתי אפשרויות: להעביר אותו לפי ערך (להעתיק את כל ה־struct) או להעביר אותו באמצעות מצביע (להעתיק רק את הכתובת). לבחירה יש השפעה משמעותית על הביצועים.

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

typedef struct {
    char name[100];
    int scores[50];
    double average;
} Student;

// לפי ערך: מעתיק ~308 בתים בכל קריאה
void print_by_value(Student s) {
    printf("%s: %.2f\n", s.name, s.average);
}

// באמצעות מצביע: מעתיק רק 8 בתים (הכתובת)
void print_by_pointer(const Student *s) {
    printf("%s: %.2f\n", s->name, s->average);
}

גם התחביר שונה. עם פרמטר מסוג ערך, משתמשים באופרטור הנקודה (s.name). עם מצביע, משתמשים באופרטור החץ (s->name).

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

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

challenge icon

אתגר

קל

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

תיצור שלושה קבצים:

  • product.h: הכרז על מבנה Product עם שלושה איברים: char name[50], double price ו-int quantity. הכרז גם על שתי פונקציות:
    • display_by_value: מקבלת Product לפי ערך ומדפיסה את המידע שלו
    • display_by_pointer: מקבלת const Product * ומדפיסה את אותו מידע
    השתמש בשומרי הכללה עם הסמל PRODUCT_H.
  • product.c: ממש את שתי הפונקציות. שים לב להבדל בתחביר: הגרסה שמעבירה לפי ערך משתמשת באופרטור נקודה (p.name), ואילו גרסת המצביע משתמשת באופרטור חץ (p->name). שתי הפונקציות צריכות להדפיס באותו פורמט.
  • main.c: צור Product, ואז קרא לשתי פונקציות התצוגה כדי להראות שהן מפיקות פלט זהה, אף שהן משתמשות בסגנונות שונים של פרמטרים.

תקבל שלושה קלטים: שם המוצר (מחרוזת), המחיר (double) ו-הכמות (מספר שלם).

בקובץ הראשי, אתחל Product עם הערכים האלה, ואז קרא ל-display_by_value ואחריו ל-display_by_pointer.

שתי הפונקציות צריכות להדפיס בפורמט הזה:

Product: {name}, Price: {price}, Qty: {quantity}

השתמש ב-%.2f עבור המחיר כדי להציג שתי ספרות אחרי הנקודה העשרונית.

לדוגמה, עבור הקלטים Laptop, 999.99 ו-5, הפלט יהיה:

Product: Laptop, Price: 999.99, Qty: 5
Product: Laptop, Price: 999.99, Qty: 5

נסו בעצמכם

#include <stdio.h>
#include <string.h>
#include "product.h"

int main() {
    char name[50];
    double price;
    int quantity;
    
    // קראו את נתוני הקלט
    scanf("%s", name);
    scanf("%lf", &price);
    scanf("%d", &quantity);
    
    // TODO: צרו משתנה מסוג Product ואתחלו אותו בערכי הקלט
    // רמז: השתמשו ב-strcpy כדי להעתיק את השם לשדה name של ה-struct
    
    // TODO: קראו ל-display_by_value עם ה-Product
    
    // TODO: קראו ל-display_by_pointer עם מצביע ל-Product
    
    return 0;
}
quiz iconבחנו את עצמכם

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

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C אונליין