שאלה על חשבון במצבעים ב cpp

Yoni Kibrik

New member
שאלה על חשבון במצבעים ב cpp

שלום, אני לא מבין את החלק של החשבון במצבעים. בספר שלי כתוב כך: נניח ש p1 הוא מצביע לשלם, שערכו 2000 (כלומר, הוא מכיל את הכתובת 2000). בהנחת שלמים בני 32 סביות, לארח הפעלת הביטוי : ;++p1 יכיל p1 את הערך 2004 ולא 2001! כל קידום של p1 יכוון אותו לשלם הבא. עכשיו אני לא מבין את זה בדיוק ואין שם דוגמה לזה אלה רק דוגמה יותר מורכבת עם מצבעים למערכים. מישהו יכול לתת לי דוגמה לקוד שעושה את מה שכתוב פה? פשוט מה שעשיתי זה כך:
#include <iostream.h> #include <stdlib.h> int main() { int *x, i; i=2000; x=&i; x++; cout<<x; system("PAUSE"); return 0; }​
והפלט הוא לא 2004 אלא: 0x254fdd4 ועים אני עושה כך:
#include <iostream.h> #include <stdlib.h> int main() { int *x, i; i=2000; x=&i; x++; cout<<*x; system("PAUSE"); return 0; }​
הפלט הוא גם לא 2004 אלא: 39124436 מה אני עושה לא נכון? תודה.
 

voguemaster

New member
השאלה קשורה באופן כללי למצביעים.

אני אנסה להסביר. ידוע לך שמצביע מכיל כתובה. ישנם כמה סוגים של מצביעים, חלקים לשלמים, לממשיים ולתווים. בוא נשתמש בדוגמת המצביע לשלם. אם אתה רושם int *p1, i; i = 10; p1 = &i; מה שקורה זה שלמעשה p1 מכיל את הכתובת של אותו שלם בזיכרון של המחשב, כאשר התוכנית רצה. אופרטור ה-& אומר: "הכתובת של.." לכן, אם אתה מדפיס את p1 , תקבל מספר שהוא למעשה מיקום בזיכרון, ולא את ערך השלם. כדי להדפיס את הערך שמוכל באותה כתובת אתה כמובן צריך להשתמש ב-*, שזה אופרטור "הערך המוכל בתוך הכתובת..". עכשיו, מה כל העניין ? בדוגמא שלהם, המצביע עצמו היה 2000 (כלומר, כתובת 2000 בזיכרון, נניח) וכאשר הגדלת אותו, הוא לא גדל ל-2001 אלא ל-2004. הסיבה היא שמספר שלם תופס בזיכרון (אם הוא 32 סיביות) 4 בתים. לכן, אם יש לך שלם שמאוכסן בכתובת 2000 ואחריו בזיכרון עוד שלם, השלם הבא יהיה ב-2004, כי 2000 ועוד גודל של שלם אחד (גודל 4) נותן 2004. המהדר יודע איזה סוג של מצביע זה, כלומר למה הוא מצביע, ויודע להגדיל אותו בהתאם לגודל הטיפוס של המשתנה. אם מספר DOUBLE תופס נניח 8 בתים, אז להגדיל את המצביע ע"י p1++ יגרום להגדלה מ-2000 ל-2008. כנ"ל אם יש מצביע למבנה בגודל 50 בתים ותעשה p1++, ערך המצביע יגדל ב-50. עכשיו לבעיות בתוכניות שכתבת: 1. יש לך משתנה שמכיל 2000. אתה מכניס ל-X את הכתובת שלו, ומגדיל את המצביע, כלומר מגדיל אותו ב-4 (כי זה גודל של שלם). כדאי לך לדעת שאף פעם דברים לא מאוכסנים בזיכרון בכתובת 2000. זו הייתה רק דוגמא לשם המחשה. הכתובת מחושבת בצורה קצת יותר מסובכת, והיא לעיתים רחוקות מספר עגול. מה שעשית זה להדפיס את הכתובת אחרי שהגדלת את המצביע בשלם אחד, כלומר, הדפסת את הכתובת של השלם הבא בזיכרון (שים לב שאין לך עוד שלם אחד, מה שאומר שנגעת באיזור בזיכרון שאסור לך!). 2. עשית את אותו הדבר, אבל הפעם הדפסת את הערך המוצבע ע"י המצביע, כלומר את השלם שהוא מצביע אליו. הבעיה היא שיש לך שלם i שמאותחל ל-2000, ואז אתה מגדיל את המצביע שלו (עכשיו מצביע לשלם הבא, שהוא לא מאותחל, ואין לך מושג מה הוא בכלל), ומציג את הערך שמאוכסן באותה כתובת. כמו שניחשת, לך תדע מה מאוכסן שם.. זה אפילו לא איזור שמותר לך לגעת בו (אבל אף אחד לא אוכף את זה!). תוכנית שתעשה את מ שאתה צריך (סליחה שזה הפוך): #include <iostream.h> #include <stdlib.h> int main() { int i, *x; i=2000; x=&i; cout << x; cout << *x; x++; cout << x; cout << *x; system("PAUSE"); return 0; } התוכנית מדפיסה את המצביע לשלם, את הערך המאוכסן בו (2000), ואז מגדילה את המצביע (כלומר עוברת לשלם הבא, שאין לנו בכלל), מדפיסה את הערך של המצביע (שים לב שהוא גדול ב-4 מהקודם, אם שלם הוא 32 סיביות) ואת מה שמאוכסן שם (שאין לנו מושג מה זה, זה במחסנית, אבל לא חשוב..) מקווה שעזרתי אלי
 

אנדרי ז

New member
פשוט מאוד

במקרה הראשון אתה צריך לרשום x=i ובמקרה השני *x=i אתה מבלבל בין ערך של פוינטר, לבין הערך שהוא מצביע עליו, לבין כתובת של משתנה. במקרה הראשון אתה מציג את הכתובת של i ולא את ערכו, ובמקרה השני אתה מתחיל את הערך שעליו מצביע x שים לב שאתה לא מאתחל את הערך הזה בשום מקום.
 
למעלה