const ב-C לעומת CPP...

const ב-C לעומת CPP...../images/Emo26.gif

בלק-אאוט קל... אני זוכר שיש הבדל בין const ב-C ל-CPP, אבל אני לא סגור מה ההבדל בהגדרות של השפות... נניח - שורה כמו:
const int moon_landing = 1969;​
יכולה להופיע בקובץ h אם מדברים על CPP (כתחליף ל-DEFINE), זה נכון גם ל-C?... אם שני קבצי implementation יעשו include לקובץ header כזה - הקומפיילר לא יצעק? (ולמה בעצם?...)
 

vinney

Well-known member
ההבדל לא בזה

מבחינת משתנים אין הבדל ב++C המילה const יכולה להתייחס לclass member function בנוסף למשתנה פשוט. הרי מהתנ"ך:
C++ Specific Declaring a member function with the const keyword specifies that the function is a "read-only" function that does not modify the object for which it is called. To declare a constant member function, place the const keyword after the closing parenthesis of the argument list. The const keyword is required in both the declaration and the definition. A constant member function cannot modify any data members or call any member functions that aren't constant. END C++ Specific​
 
אני מדבר על const במשתנים...

אתה בטוח שאין הבדל?? אני אגיד לך איפה באה לי הבלבלה - קיבלתי קובץ header כללי (מכיל הגדרות בסיסיות וטיפוסים בסיסיים שמשמשים את כל הפרויקט). הפרוייקט כתוב ב-CPP. יש שם בעיקר typedef-ים והגדרות של struct-ים, אבל בין השאר יש שם הגדרת משתנה const כמו הדוגמה שנתתי קודם. עכשיו... אני כותב מודול שכתוב בשפת C, שבו שני קבצי C שונים משתמשים ב-header הזה. מן-הסתם הוא לא מתקמפל כי הוא מתלונן שהמשתנה const הזה מוגדר לו פעמיים... ואז בא הבלק-אאוט: 1) 100% שהוא לא מתקמפל - את זה אני מבין, אבל למה לעזאזל הוא כן התקמפל בפרויקט ה-CPP?? 2) מה הדרך היותר "נכונה" לשכתב את השורה הזו ב-C סטנדרטי: להפוך את זה ל-define או להוסיף static?... (או פתרון אחר?)
 

vinney

Well-known member
אז לא הבנתי מה הקשר

אם יש לך משתנה שמוגדר פעמיים - ברור שתקבל שגיאה, בין אם הוא CONST ובין אם לא. מה שכן, הגדרת CONST בלי הערך זה כמו PROTOTYPE, אתה יכול לכתוב את זה כמה פעמים שאתה רוצה. לעומת זאת הגדרת CONST עם ערך יכולה להיות רק פעם אחת בSCOPE. זה נכון לC ול++C באותה מידה.
 
תקרא שוב - ../images/Emo26.gif

זה בדיוק מה שאני לא מבין - למה ב-CPP זה התקמפל בכלל... אבל שים-לב: פיסית הוא לא "מוגדר פעמיים" - הוא מוגדר בקובץ H ששני קבצים עושים לו include (שבפועל זה בדיוק אותו הדבר). אם הוא היה מוגדר כ-static אז זה אמור להיות בסדר... אבל זה לא static...
למה לעזאזל זה עובר ב-CPP??
 

vinney

Well-known member
לא ברור

ניסיתי לעשות את זה אצלי וקיבלתי שגיאה אתה בטוח שאין שם איזה IFDEF מוסתר שמוריד לך את הקטע הזה? עקרונית אין הבדל בין C ל++C בקטע הזה. STATIC מגביל את הSCOPE של המשתנה הזה, תראה שזה לא פוגע לך במשהו אם אתה מכניס אותו.
 
נראה לי שאתה מפספס...../images/Emo26.gif

השורה הזו יושבת בתוך header file ככה שברור זהוא מוקף ב-ifndef, define - אבל זה לא משנה, כי ברגע ששני קבצי c עושים לו include - הוא עדיין יקרא (ויתקמפל, ויתלנקג') פעמיים... static אני מניח, לא ישנה - כי הוא יגביל את ה-scope בדיוק לקבצים שעושים לו include וזה (אני מקווה
) יהיה בסדר...
 
יש הבדלים בין השפות

ב C משתנה שמוגדר const הוא כמו כל משתנה אחר למעט העובדה שאי אפשר לשנות אותו. פירוש הדבר שהקומפיילר מקצה מקום וקיבלת שגיאת לינקר (ככל הנראה). ב ++C משתנה const יכול לשמש גם כ symbolic constant. הקומפיילר לא יקצה מקום למשתנה הזה אלא יציב את ערכו בקוד (למעט אם לקחת את הכתובת שלו). אתה יכול לפתור את הבעיה במספר דרכים: - קומפילציה שונה ל++C וC עם ifdef# - לשנות את הקבועים הסימבוליים ל enum (בהנחה שהם שמשו רק לזה) - להשתמש בפרה-פרוססור עם define#
 

vinney

Well-known member
זה כבר עניין לאופטימיזציות

מבחינת ++C וC הקוד הזה הוא תקין :
const int moon_landing = 1969; #include <stdio.h> int main(void){ const int *ptr = &moon_landing; printf ("%X", ptr); getchar(); return 0; }​
הקומפיילר יודע שאני צריך את הכתובת זכרון, ולכן לא יבצע אופטימזציה שמציבה את הערך במקום המשתנה. זה לא משנה מאומה מבחינת כתיבת קוד. השגיאה שאורי מדבר עליה לא באה מלינקר (אני מקווה). ולא צריך לעשות קומפילציה שונה לC ו++C רק בגלל CONST, זה לא נכון ולא יפה. צריך כמה שפחות IFDEFים בקוד.
 
דוגמא תעזור להבין

למשל הקוד הזה תקין ב ++C אבל לא ב-C
const int Buff_Size = 100; // .... char array[Buff_Size];​
אין כאן קשר לאופטימיזציות.
 
תודה גם כאן...../images/Emo45.gif

זה מה שהייתי צריך... אבל נשארו השאלות ששאלתי למטה (למה זה לא עבד עם ++g למשל...) מה קובע אם ה-const הוא symbolic constant (כמו DEFINE ב-C) או אם הוא const כמו ש-const ב-C?... זה איך שמתחשק לקומפיילר?.. ב"קומפילציה שונה ל++C וC" בכוונה להקיף את הקטע ב- ifdef __cplusplus? קצת מכוער, לא?... מה לגבי לשנות ל-static const?... זה יתפוס גם ב-C וגם ב-CPP, לא?...
 

zagzagzag

New member
יש הבדל בקישור

ב-CPP ‏ל-const שהוגדר מחוץ לפונקציה יש internal linkage, כלומר הוא לא מוכר מחוץ לקובץ, ולכן כשאתה מגדיר את ה-const ב-header לא תהיה לך בעיה של כפילויות. ב-C לעומת זאת, ל-const שהוגדר מחוץ לפונקציה יש external linkage, ולכן אתה מקבל שגיאה. ב-++Thinking in C יש פרק על const שמסביר את העניין הזה.
 
הופה!! תודה....../images/Emo45.gif../images/Emo26.gif

OK, אז זה מסביר למה ב-CPP זה עובד, וב-C לא. עכשיו יש כמה שאלות: 1) אם אני צריך להשתמש בזה ב-C, לשנות את ה-const ל-const static או ל-DEFINE?... (נראה לי ששניהם יעבדו, השאלה מה יותר אלגנטי) 2) ניסיתי עכשיו לעשות קטע קוד כזה ב ++g והוא דווקא לא התקמפל!... (ב-VC הוא התקמפל כרגיל, ולא התקמפל כשהדלקתי את ה-"Disable Language Extensions")...
 

vinney

Well-known member
אוקי, אז חידשתם לי../images/Emo13.gif

אבל לפי ההסבר של זאג, הפתרון הוא STATIC - זה יתן לך בדיוק את אותה התוצאה בהיבט הSCOPE.
 
דווקא בהיבט של SCOPE,

זה לא יהיה אותו הדבר... כי במצב של היום (כשהקובץ משמש פרוייקט CPP) המשתנה הוא משתנה גלובלי לכל דבר.... ומוכר בכל מקום בתוכנית... static יגביל את ה-scope רק למי שיעשה include לאותו header... (שזה 100%, רק צריך לוודא שזה לא דופק אחורה את הפרויקט...)
 
למעלה