extern, const ו static אחת ולתמיד

pertal

New member
extern, const ו static אחת ולתמיד

אני יודע שהרבה מתבלבלים בין אלה. האם תוכלו להסביר לי מה התפקיד של כל אחד?? (כמובן ב c) האם ההבדל בין static ל const, הוא שאחד מהם שומר ערך שאי אפשר לשנות אותו בשום דרך, והשני מגדיר משתנה שיהיה לוקאלי לפונקציה, זתומרת שהפונקציה תוכל לשנות אותו, אבל שאר התוכנית לא תוכל לפנות אל המשתנה הספציפי הזה, אבל תוכל להשתמש במשתנה אחר עם אותו השם?? (כי הרי הראשון חי רק בפונקציה.) האם extern פשוט מגדיר משתנה או פונקציה "חיצונית" ?? זתומרת אם אני מגדיר extern איפהשהוא לדוגמא בקובץ 1.c ואני גם משתמש בקובץ 2.c לפרוייקט, אז בקובץ 2, אני יכול לפנות לאותו המשתנה, והוא יהיה "קיים" בכל הפרוייקט?? אותו דבר עם פונקציות-קריאה לפונקצית extern שממוקמת ב 1 מתוך קובץ 2? עכשיו לשאלה-האם מישהו יכול להגיד לי אם קלעתי אפילו קצת, ולהסביר קצת על ההבדלים בניהם?? ויש עוד משהו (סוג) שאני צריך לדעת חוץ מה3 האלה?
 

selalerer

New member
:::::::::::::::::::::::::::::::::

static אתה יכול להגדיר את המשתנה בתוך פונקציה, אבל ערכו ישמר מריצה לריצה של הפונקציה והאיתחול שלו יעשה פעם אחת בלבד, בעת הריצה הראשונה של הפונקציה. כלומר הוא יהיה גלובאלי, אבל אף אחד לא יכול לגשת אליו מלבד הפונקציה. לדוגמא:
void count() { static int c=0; printf("%d",c); c++; }​
תריץ אותה כמה פעמים ותראה את התוצאה. const לא ניתן לשינוי. המצב פשוט כאשר אתה מכריז על const int או char, מה ששונה מdefine# הוא שזה נוכח בזיכרון ואתה יכול לקבל כתובת שלו, או לשלוח לפונקציה מצביע אליו. המצב קצת מסתבך כשמדובר במצביעים, שם המצביע יכול להיות לא ניתן לשינוי, או המוצבע. אם אני לא טועה אז ככה הערך המוצבע הוא הקבוע:
const int *pi;​
וכך המצביע עצמו הוא הקבוע:
int i; int *const pi=&i;​
יש עוד צורת כתיב אחת (עם הconst בין הint ל*) אבל אני לא זוכר מה משמעותה ויש גם const בסוף הכרזה על פונקציה שאני לא זוכר מה משמעותו. אני ממליץ לקרוא ב++Thinking in C (אפילו שזה לא ספר על C), יש שם הסבר טוב. extern פה מדובר על מצב שמשתנה נמצא בקובץ C אחר (מה שישים אותו אח"כ בקובץ object נפרד) ואתה רוצה להכליל קובץ h שמכריז על המשתנה הזה, אבל מבלי ליצור מופע נוסף שלו. אז אתה כותב בקובץ h כך:
extern int data;​
ואז מה שנפרש לך לתוך הקובץ C שעושה include# לקובץ הזה זה לא הכרזה רגילה על int אלא הכרזה על extern int, מה שאומר לקומפיילר לא ליצור מופע נוסף של int אלא לחכות לשלב הlink שם יתברר מיהו המשתנה הזה והיכן הוא נמצא, אז פשוט שים סימן לlink פה יש משתנה בשם זה וזה מקובץ אחר. אני מקווה שהבנת, באופן כללי ++Thinking in C מסביר היטב את הדברים הללו, אפילו שהוא לא ספר לC, אני ממליץ לקרוא ממנו את הפרקים על זה בכדי להבין טוב יותר.
 

IP yuval

New member
../images/Emo45.gif קצת תוספות:

static יכול לשמש גם למשתנה או פונקציה גלובלית בתוך קובץ בשביל שיוכלו להשתמש בהם רק בקובץ הזה. int const* p זה מצביע לקבוע, זה בעיקר בשביל לבלבל. const בסוף הכרזה על פונקציה או לפני המימוש זה רק בC++ לפונקציות חברות במחלקה, מה שמציין שהפונקציה לא משנה שום דבר באובייקט.
 

Metheny

Member
אז..

מה ההבדל בין אם ה- const הוא לפני ה-int לבין אם הוא בין ה-int וה-* ?
 

galh

New member
יש הבדל.

מצביע קבוע למידע לא קבוע לעומת מצביע לא קבוע למידע קבוע.
 

IP yuval

New member
תבדוק בעצמך:

int main() { int a = 24; int b = 24; const int * p1 = &a; int const * p2 = &a; int * const p3 = &a; /* Errors: */ /* *p1 = b; *p2 = b; p3 = &b; */ p1 = &b; p2 = &b; *p3 = b; return 0; }​
 

galh

New member
בדקתי פעם, לא מספיק? ../images/Emo13.gif

נראה לי שאנחנו מדברים על שני דברים שונים:
const char* p char* const p​
בראשון ניתן לשנות את המצביע, אבל לא את המידע. בשני המצביע קבוע, אבל ניתן לשנות את המידע שעליו הוא מצביע.
 

Metheny

Member
הבהרה

הוא מתכוון להבדל (או יותר נכון חוסר הבדל, לפי מה שאמרו פה) בין השניים הבאים:
const char * p char const * p​
 

ahab

New member
אין הבדל

זה תלוי רק במיקום ה-const - משמאל או מימין ל-*.
 

ahab

New member
הממ.... לא

בדוגמא של יובל, אין הבדל בין p1 ל-p2. שוב: const int * p1 - מצביע ל-int קבוע (אי אפשר לשנות את ה-int דרך המצביע) int const * p2 - מצביע ל-int קבוע (אי אפשר לשנות את ה-int דרך המצביע) int * const p3 - מצביע קבוע ל-int (אי אפשר לשנות את המצביע (את הכתובת אליה מצביע p3 םם)) const int * const p4 - מצביע קבוע ל-int קבוע (אי אפשר לשנות את המצביע, או את ה-int דרך המצביע) שים לב שבמקרים 1, 2, ו-4, ה-int המוצבע לאו דווקא קבוע. פשוט אי אפשר לשנות אותו בעזרת המצביע (;3 = p1* נותן שגיאת קומפילציה).
 
למעלה