מערך דו\תלת\רבע מימדי ו c++

dedtheded

New member
מערך דו\תלת\רבע מימדי ו c++

איך אפשר לקבל מערך דו מימדי או תלת מימדי כפרמטר לפונקציה? בר.
 

gmorphus

New member
יש שתי דרכים

לגבי מערך דו מימדי, זה תלוי איך אתה מגדיר אותו. אם הוא קבוע ולא מבוסס על מצביעים אתה יכול פשוט [int name[num_rows][num_cols אבל אם הוא מבוסס על מצביעים אתה צריך להתשמש ב int **2d_array. לגבי מערכים במימדים יותר גדולים לא ממש ניסיתי אבל עם מצביעים זה תמיד עובד: int ***3d_array, וכן הלאה. צריך לדעת לטפל בזה כמו שצריך אבל זה אפשרי.
 

dedtheded

New member
שאלה נוספת

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

erezsh

New member
פשוט מאוד

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

erezsh

New member
אז זהו

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

dedtheded

New member
אז זה אומר ש

אני יכול להגדיר מצביע במקום להגדיר מערך??
int* Arr1; Arr1[2]=5;​
בר.
 

selalerer

New member
לא.

מערכים (חד מימדיים) בC בנויים ממצביע ואוסף זיכרון רציף. כשאתה מגדיר מערך ככה:
int arr[20];​
אתה בעצם מגדיר גם מצביע וגם 20 intים. כשאתה מגדיר מצביע כך:
int *arr;​
אתה מגדיר רק את המצביע אך לא את התאים שאליהם הוא מצביע. בכדי לגרום לו להצביע לתאים אתה צריך להקצות לו זיכרון כך:
int *arr; arr=malloc(sizeof(int)*20); arr[19]=257; free(arr);​
או בגרסה הC++:
int *arr; arr=new int[20]; arr[4]=257; delete []arr;​
כמובן שיותר קל להכריז על מערך בצורה הרגילה (וגם אתה לא צריך לדאוג לשחרר את הזיכרון) אבל לעיתים אתה לא יודע מה יהיה גודל המערך מראש אלא רק בעת ריצת התוכנית.
 

IdanR

New member
אממ.. נסחפת קצת..

**int מצביע למצביע . כלומר, זה יכול להיות מצביע למקום בזיכרון, שהוא בעצם האיבר הראשון במערך של מצביעים, שכל אחד מהם מצביע למקום בזיכרון שהוא int .(ולא עוד מצביע כמו שאמרת, שזה כבר שלושה הצבעות.. ) , ובעצם יכול להיות האיבר הראשון במערך של מספרים . סרטוט (לפחות ניסיתי): p (מצביע מסוג **) / / / / / 2, 1, 0 (כל אחד מאלה הוא מצביע מסוג *) | | | 0 0 0 (האיבר הראשון במערך שכל איבר בו הוא int) 1 1 1 (האיבר השני, וכו'... ) 2 2 2 3 (שימו לב שבהקצאה דינמית כל טור יכול להיות בגודל שונה)
 

eyalbd

New member
מערך רב מימדי כפרמטר

כאשר מעבירים מערך רב מימדי לפרמטר חייבים להעביר את כל המימדים למעט הראשון. דוגמא:
void display_3dim_array(int array[][DIM2][DIM3]) { for (int i = 0; i < DIM1; ++i) for (int j = 0; j < DIM2; ++j) for (int k = 0; k < DIM2; ++k) cout<< "A(" << i << "," << j << "," << k << ") = " << array[j][k] << endl; }
 

erezsh

New member
שוב, מדובר פה על

להבין כיצד בנוי מערך. גודלו של מערך ב-C/C++, כלומר מספר איבריו, לא נשמר. השפה רק מאתחלת את המקום המבוקש, ומשם סומכת על המתכנת שלא יחרוג מהגבולות (היא אינה מבצעת בדיקות). אבל ברגע שמתחילים להתעסק במערכים דו-מימדיים ומעלה, הגודל של המערך נעשה מידע נחוץ על מנת לייצר את ה-Offset הנכון (ועל טרנסלציה של מערך רב-מימדי לחד-מימדי, פנה ל-Tutorial הקרוב לביתך).
 

eyalbd

New member
הסבר על מטריצה דו מימדית.

כאשר את יוצר מטריצה 3X3 הקומפיילר לא מסדר זאת בסידור מיוחד אלא מקצה בלוק של 9 איברים. עכשיו נניח שאתה רוצה את איבר 1,2. הקומפיילר צריך לקפוץ לאיבר שמתאים לשורה מס' 1 עמודה 2. על מנת לבצע חישוב נכון הקומפיילר חייב לדעת את מספר העמודות משום שהאיבר הנ"ל נמצא בבלוק המקורי במקום:
i * COLUMNS + j​
במקרה שלנו:
1 * 3 + 2 (= 5)​
כאשר אתה מעביר מערך רב מימדי כפרמטר הקומפיילר מעביר לפונקציה בזמן ריצה את הכתובת של האיבר הראשון אבל הוא צריך לדעת את מספר העמודות בזמן קומפילציה. הקומפיילר צריך לקפוץ מהאיבר ההתחלתי (כתובת האיבר הראשון) לאיבר החמישי (מתחילים מאפס) כמו בחישוב שהראיתי. בפועל מתבצע קוד כזה:
A[1][2] == *(&A[0][0] + 1 * COLUMNS + 2)​
 

dedtheded

New member
ומדוע לא את המימד הראשון

אז למה לא מעבירים גם את המימד הראשון? בר.
 

eyalbd

New member
כי לא צריך אותו לחישוב הקפיצה

אתה יכול להעביר מה שאתה רוצה. לקומפיילר לא איכפת והוא לא יתייחס למה שאתה מעביר. תסתכל בהסבר הקודם שלי אם נחוץ לדעת את מספר השורות כדי להגיע חאיבר מסויים.
 

gmorphus

New member
זה בתנאי שהמערך מוקצה סטטית

כלומר על המחסנית. אם אתה רוצה לעבוד עם מערכים של מצביעים למצביעים אתה צריך להעביר את זה בהתאם, כלומר int ***3d_array. כמובן שגם להקצות בהתאם את המקום. מבחינת ההתייחסות למערך, לאיברים הספציפיים שלו זה זהה בשני המקרים. כלומר, אם אמרנו שמצביע למערך של מצביעים לint. כלומר int **2d_arr, הוא מערך דו מימדי, כי למעשה כל תא במערך הוא מציע לעוד מערך. אז ההגדרה int ***3d_arr תהיה מצביע למערך תלת מימדי. כלומר יש לנו פה מצביע למערך של מצביע למערכים דו מימדיים.
 

eyalbd

New member
מה פתאום?

הקוד הזה יעבוד בלי בעיה:
int (*dynamic)[3][3] = new int[DIM1][DIM2][DIM3]; //... display_3dim_array(dynamic); // Let's print whatever.... // display_3dim_array( new int[DIM1][DIM2][DIM3] );​
 

eyalbd

New member
התוכנית cdecl

זו תוכנית שמסבירה במילים הכרזות מסובכות ב-C. מומלצת למי שלומד. הנה למשל session שהרצתי אחרי התשובה הקודמת:
cdecl> explain int A[1][2][3] declare A as array 1 of array 2 of array 3 of int cdecl> explain int* A[2][3] declare A as array 2 of array 3 of pointer to int cdecl> explain int (*A)[2][3] declare A as pointer to array 2 of array 3 of int cdecl> explain void Func(int [][2][3]) declare Func as function (array of array 2 of array 3 of int) returning void cdecl>​
 
למעלה