מערך דו מימדי

voguemaster

New member
כן

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

yair24

Member
הוא אומר שם משהו כזה:

לא חייבים להשמיט את הערך הראשון, בגלל שאין בדיקת גבולות... מה הכונה שלו? הכונה היא שאם אני מגדיר משהו כזה:
void myfunc(char a[])​
ועכשיו אני קורא לפונקציה הזאת עם פוינטר למערך שמוגדר ככה:
void main() { char yoyo[10]; myfunc(yoyo); } ועכשיו נגיד שהפונקציה MYFUNC היא פונקציה שכותבת 20 ערכים לתוך המערך שהגיע אליה כפרמטר, אז היא בעצם תיכתוב בפועל 20 ערכים ותבצע גלישה החוצה כי אין בדיקת גבולות? עכשיו על אותו משקל אני יכול לעשות פונקציה שלוקחת מערך דו מימדי ולא לתת לה את המימד הראשון (או יותר נכון לפי המאמר גם אם אני נותן את המימד הראשון זה לא עוזר כי אין בדיקת גבולות...) ולקרוא לפונקציה עם מערך שהמימד הראשון שלו יותר קטן ממה שהפונקציה מטפלת ושוב תהיה כאן גלישת זיכרון... לא? יאיר​
 

yair24

Member
נראה לי ששכחתי לסגור איזה תג...

ועכשיו נגיד שהפונקציה MYFUNC היא פונקציה שכותבת 20 ערכים לתוך המערך שהגיע אליה כפרמטר, אז היא בעצם תיכתוב בפועל 20 ערכים ותבצע גלישה החוצה כי אין בדיקת גבולות? עכשיו על אותו משקל אני יכול לעשות פונקציה שלוקחת מערך דו מימדי ולא לתת לה את המימד הראשון (או יותר נכון לפי המאמר גם אם אני נותן את המימד הראשון זה לא עוזר כי אין בדיקת גבולות...) ולקרוא לפונקציה עם מערך שהמימד הראשון שלו יותר קטן ממה שהפונקציה מטפלת ושוב תהיה כאן גלישת זיכרון... לא? יאיר
 

yair24

Member
וורלורד

תגיד אתה פה מהיום שהפורום נוסד נכון? יאיר
 

yair24

Member
זוכר את פגישת הצאט שהיתה

צריכה להיות לכל חברי הפורום. יאיר
 

WarLord

New member
בוודאי ../images/Emo70.gif

אני הייתי שם... לבד
 

jgut

New member
ניראה לי שאתה צודק

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

ke

New member
הסבר

הרעיון הוא כזה, שאתה מעביר מערך מועברת הכתובת של התא הראשון במערך (תא מספר 0) ולכן לקרוא לפונקציה אם
int a[10]; func(a,10); או func(&a[0],10);​
זה אותו הדבר. כל מה שהקומפיילר עושה זה להעביר את הכתובת הראשונה, ולכן אין כל בדיקת גבולות. מה שחשוב הוא לדעת את סוג אלמנטים במערך, כדי שאם בתוך הפונקציה יש קריאה למשל,
cout << a[1] << endl;​
אז הקומפיילר מחשב את הגודל לפי כתובת = כתובת ראשונה + אינדקס * גודל של אלמנט (במקרה שלנו האלמנט זה int). ובמקום int יכול לבוא כל דבר אחר (למשל struct) וגם למשל מערך, כלומר מערך של מערכים, וזה בעצם מערך דו מימדי. כלומר מה שחשוב להבין זה שמערך דו מימדי הוא מערך של מערכים, ואין לו איזה "ישות" מיוחדת (כמו בפסקל, אם אני לא טועה). ולכן כשאתה מגדיר מערך int a[3][4] אתה בעצם מעביר מגדיר מערך בגודל שלוש, שכל אלמנט (מהשלושה) הוא מערך בגודל 4. ולכן הקומפיילר חייב לדעת מה הגודל של אלמנט במערך, ולכן ה 4 חייב להיות מועבר לפונקציה. באותו אופן אם אתה מגדיר מערך תלת מימדי int a[2][3][4] אז הגדרת מערך של 2 אלמנטים. כל אלמנט הוא מערך דו מימדי של 3*2 (והמשך ההגדרה ברקורסיה...) אפשר לקרוא על זה ב K & R בעמודים 110-112
 

yair24

Member
אבל מה שאתה אומר כאן

מבטל את מה שאמרנו עם המכפלות... שורה * אורך שורה + עמודה לא? יאיר
 

WarLord

New member
לא

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