/* A demonstration program to show how arrays of dynamic dimensions can be obtained by cutting pieces of any required length from a single large array. Two arrays, Elts and Rows, are used. Elts contains 1000 floats, used for the elements of the smaller dynamic arrays. Rows is an array of 100 pointers, used as pointers to the individual rows of the dynamic arrays. Two pointers, NextElt and NextRow, point to the first unused element of each array (so we know where the next allocation should start). Finally, EltsLeft and RowsLeft are two ints telling how many elements still remain unallocated. The initial state of these variables is shown in this picture (the lines might not display properly on some computers): NextElt: NextElt: ÚÄÄÄ¿ ÚÄÄÄ¿ ³ . ³ ³ . ³ ÀÄÅÄÙ ÀÄÅÄÙ ³ Rows: Elts: ³ Eltsleft: ³ ÚÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ÚÄÄÄÄÄÄ¿ ÀÄÄÄÄ>³ ³ ³ ³<ÄÄÙ ³ 1000 ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ÀÄÄÄÄÄÄÙ ³ ³ ³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ ³ Rowsleft: ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ÚÄÄÄÄÄÄ¿ ³ ³ ³ ³ ³ 100 ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ÀÄÄÄÄÄÄÙ ³ ³ ³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ . ³ ³ . ³ . . . . Suppose the calling program allocates an array of 2 rows and 3 columns (6 elements in all), and assigns the address of the allocated array to a variable called UserA (of type float**). Then the picture should change from the above to: NextElt: UserA: NextElt: ÚÄÄÄ¿ ÚÄÄÄ¿ ÚÄÄÄ¿ ³ . ³ ÚÄÄÄÄÄÄÄÄÄÅÄ. ³ ³ . ³ ÀÄÅÄÙ ³ ÀÄÄÄÙ ÀÄÅÄÙ ³ ³ Rows: Elts: ³ Eltsleft: ³ ³ ÚÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ÚÄÄÄÄÄÄ¿ ³ À>³ .ÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ>³UserA[0][0]³ ³ ³ 994 ³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ÀÄÄÄÄÄÄÙ ³ ³ .ÄÅÄÄÄÄÄÄÄ¿ ³UserA[0][1]³ ³ ³ ÃÄÄÄ´ ³ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ÀÄÄÄÄ>³ ³ ³ ³UserA[0][2]³ ³ Rowsleft: ÃÄÄÄ´ ³ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ÚÄÄÄÄÄÄ¿ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄ>³UserA[1][0]³ ³ ³ 98 ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ÀÄÄÄÄÄÄÙ ³ ³ ³UserA[1][1]³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ ³UserA[1][2]³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ ³ ³<ÄÄÙ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ ³ ³ ³ ÃÄÄÄ´ ÃÄÄÄÄÄÄÄÄÄÄÄ´ ³ . ³ ³ . ³ . . . . From these pictures it should be clear what the allocation function must do: Assign suitable values to the pointers in the Rows array, adjust the RowsLeft and EltsLeft values, adjust the Next.. pointers, and return the address of the first allocated Rows value. */ /* Set up 'resource' variables: */ #define ESIZE (1000) #define RSIZE (100) float Elts[ESIZE], *NextElt = Elts; float *Rows[RSIZE], **NextRow = Rows; int EltsLeft = ESIZE, RowsLeft = RSIZE; #include float ** makearray(int rows, int cols) { /* Allocates space for an array of size rows*cols. Returns the address of the array, or NULL for failure. */ int size = rows * cols; float ** array_address; /* Check for enough space: */ if (rows > RowsLeft || size > EltsLeft) { /* no space? */ return NULL; } /* We now know the allocation will work: adjust the counts for remaining Rows and Elts after this allocation has been made. */ RowsLeft -= rows; EltsLeft -= size; /* Now remember the starting row, as that is the value to return later. */ array_address = NextRow; /* In a loop, assign the row pointers, and advance the Next.. pointers: */ while (rows > 0) { *NextRow = NextElt; /* Fill in a pointer */ NextElt += cols; /* Advance over the elements for this row */ NextRow++; /* Point to next Rows element */ rows--; /* Decrement count of rows to process */ } return array_address; } /***** The following main function tests the allocator by allowing the user to specify sizes for arrays to be allocated. Successive arrays are allocated to the same 'array' variable, called 'Array'. That means that the pointer to previous arrays is lost as each new one is allocated. That would not be acceptable in a serious program, but it is fine for this demo. */ #include main () { float ** Array; /* Once an array is allocated to this variable, it may be used with two subscripts, just like an ordinary two-dimensional array. */ int i, j, r, c, size; float *p; /* a temporary pointer */ printf("Enter array row & column size: "); scanf("%d %d", &r, &c); while (r >= 0 && c >= 0) { /* Keep trying as long as dimensions are sensible. */ Array = makearray(r, c); if (Array == NULL) { printf("Failure to allocate array.\n"); exit(0); } /* Here, Array[0] is the first element of Rows that belongs to this array. It is the address of the first element of Elts that belongs to this array. To test whether the allocator has worked properly, we can allocate successive integral values to those elements of Elts that should be in the array. Then, if we display them using array subscript notation, the successive values should be displayed. */ size = r * c; p = Array[0]; for (i=0; i