Explore the mysteries of C/C ++ arrays and pointers in depth: Dynamic Arrays
When I write down this question, I feel very hard. In essence, the content described in this chapter is different from the concept stated in the title. In programming, we often need to process a piece of data with unknown length, and the length may change during running, the current C/C ++ standard does not provide implementation in the stack segment and Data Segment memory, but only in the heap. For example, you can allocate a memory segment in the heap as shown in the following code, to process a group of uncertain integers:
Int * P = (int *) malloc (N * sizeof (INT ));
Now we often refer to this heap memory as a "dynamic array ". Is this correct? Array is a high-level concept and an important component of the C/C ++ object model and type system. An object to be an array, the expression or identifier that references this object must have a high-level array type, but this memory does not reference any array type and there is only one pointer to it. Therefore, this memory segment is not an array of C/C ++ high-level semantics. Although P can use the subscript operator to access data in the memory block, it only benefits from the pointer nature of the subscript operator (as described in Chapter 4. A real dynamic array not only has a variable length during runtime, but also needs to have an array type abstraction, which requires the support of language rules. These conditions are not available in P. However, the real implementation of dynamic arrays is not easy, and it is often restricted by multiple factors such as efficiency. Even if it is implemented, it may have to pay a large price, which outweighs the loss. For this reason, the C/C ++ standard does not support dynamic arrays. However, this heap memory is called a "dynamic array" for many years and has become a natural phenomenon. I did not rename it for technical skills and qualifications, so it is just a stream-by-stream. It is also called a dynamic array for the moment, it is important to understand the essential differences between the two.
Since dynamic arrays are not really dynamic arrays supported by C/C ++ rules, we need to construct the addresses of each dimension in the array through pointers before the subscript operator can be used for the entire array. This divides the internal structure of the dynamic array into two parts, namely, the data storage area, which is used to save the real array elements, and the other part is called the intermediate address buffer zone, saves the center address of each dimension in the array.
Based on the spatial continuity of the data storage area, dynamic arrays can be divided into two categories: Dynamic Arrays with continuous storage space and dynamic arrays with non-continuous storage space. They are called continuous dynamic arrays and discrete dynamic arrays respectively.
Discrete Dynamic Array is the simplest dynamic array, because you do not need to consider where the data is stored, you only need to dynamically allocate it. At the same time, the intermediate address does not need to be obtained or simply calculated. For example, a two-dimensional discrete dynamic array can be constructed as follows:
Int ** P = (INT **) malloc (M * sizeof (int *); </P> <p> for (I = 0; I <m; ++ I) </P> <p> P [I] = (int *) malloc (N * sizeof (INT ));
In the above Code, P points to the intermediate Address Buffer and stores the first address of each element in the first dimension. P [I] points to the data storage area, which is not consecutive. To release a space, perform the following operations:
For (I = 0; I <m; ++ I) </P> <p> free (P [I]); </P> <p> free (P );
A discrete dynamic array is used to construct an intermediate Address Buffer and a data storage zone. This is the reason for the discontinuous data space. Although the construction process is simple, non-continuity brings many disadvantages. First, it is not conducive to direct addressing within the array. For example, the element address is calculated through the first address in the data area. Second, the process is complicated when the length of the array needs to be changed; third, space release requires re-traversing the intermediate address buffer. However, you can create a data storage area and an intermediate address buffer area. This method makes it possible to store continuous data, continuous Dynamic Arrays do not bring the disadvantages of discrete dynamic arrays. The following is an example of constructing a continuous dynamic array:
Int * P = (int *) malloc (M * n * sizeof (INT); </P> <p> int ** q = (INT **) malloc (M * sizeof (int *); </P> <p> for (I = 0; I <m; ++ I) </P> <p> q [I] = P + I * N;
First, P allocates M * n int data storage areas, and then Q constructs an intermediate address based on this space. Now, you can not only use this array through Q [m] [N], but also directly access the elements of the array through the P and subscript operators. You can release p and q directly when releasing the space. To change the length of the array, you only need to re-allocate the space pointed to by P and re-construct the intermediate address buffer, for example, to change the array of M * n int elements to K * j int elements, you can do this:
Int * P = (int *) realloc (P, K * j * sizeof (INT); </P> <p> int ** q = (INT **) realloc (Q, K * sizeof (int *); </P> <p> for (I = 0; I <K; ++ I) </P> <p> q [I] = P + I * J;
The discrete dynamic array must first dynamically allocate K * j int space, then copy the old data, and then release the old space. The whole process is much more difficult than the continuous space.
Continuous Dynamic Arrays can not only use the space in the heap, but also be constructed in the stack segment and data segment. You only need to re-construct the intermediate address in the array object of the stack or data segment. For example:
Double A [100]; </P> <p> double ** P = (double **) malloc (5 * sizeof (double *)); </P> <p> for (I = 0; I <5; ++ I) </P> <p> P [I] = a + I * 20;
In this way, the space of one-dimensional double array a is transformed into a two-dimensional array P [5] [20] logically. Note that the length of the re-constructed dynamic array cannot exceed the space of, otherwise, the results are uncertain and dangerous.
In the preceding example, a two-dimensional array is constructed on a one-dimensional array, and the dimension changes. This shows that continuous dynamic arrays can not only easily change the length, but also easily change the dimension. When the target dimension is variable, recursive algorithms are required to construct the intermediate address. The author's blog provides an example of an array ADT with variable dimensions.
Note that the intermediate address of the dynamic array does not belong to the array type. For example, the first-dimensional Q [m] type of the above dynamic array Q [m] [N] is still int *, the first dimension a [m] of an array object int A [m] [N] is an array type int [N].
In summary, continuous dynamic arrays have many advantages over discrete dynamic arrays, so continuous dynamic arrays should be used first in programming practice.
Original article: http://blog.csdn.net/supermegaboy/archive/2009/11/23/4854899.aspx.