------------------------------------------- Section 0 preface -------------------------------------------
Write a simple YUV library, which is stuck in the issue of Dynamic Allocation of multi-dimensional arrays. Alas, the basic skills of C are not solid, so it took me one afternoon to explain it to myself. Refer to C expert programming. The level is limited. You are welcome to correct it.
----------------------------------------- Section 1 left and right -------------------------------------
The compiler assigns an address (left value) to each variable. This address is known during compilation, and the variable remains at this address during runtime. The value (right value) of the variable stored in this address is only known at runtime. Therefore, if the compiler needs an address to perform an operation, it can directly perform the operation. If a variable value is required, it needs to issue commands to read variable values from a specified address and coexist in registers. Here, we can understand that as a pointer variable, its own address is the left value, and its variable value (that is, the address value pointing to) is the right value. Therefore, the pointer must first obtain its current value at runtime before unreferencing it.
The array name is a left value, that is, the location in the memory. However, the array name is an unchangeable left value, that is, it cannot be assigned a value.
Int main ()
{
Int A [3] = {0 };
Int B = 1;
A = & B; // error: "=": The left operand must be an L value.
Return 0;
}
--------------------------------------- Section 2 array and pointer difference ---------------------------------
Example:
Int main ()
{
Char arr [4] = "ABC"; // Note 1
// Char arr [4] = {'A', 'B', 'C', '\ 0'}; // Note 2
Char * PTR = "ABC"; // Note 3
// PTR + 1 = & arr [2]; // Note 4
Printf ("arr: % x, % x, % x \ n", & arr, & arr [0], & arr [1]); // Note 5
Printf ("PTR: % x, % x, % x \ n", & PTR, & PTR [0], & PTR [1]);
Return 0;
}
Note 1 & 2 is equivalent. Its structure is as follows:
A B C \ 0
[_] [_] [_] [_]
12fed4 + 1 + 2 + 3
Note 3 has the following structure:
42703c a B C \ 0
[_] [_] [_] [_] [_]
12fec8 42703c + 1 + 2 + 3
Note 4 Review Section 1. Obviously, p + 1 first needs to know the value of P (the right value), which can only be obtained at the runtime. It is obviously incorrect to assign a value to the address where p is located at the Compilation Time.
Note 5 verifies note1 and 3. The running result is as follows:
Arr: 12fed4, 12fed4, 12fed5
PTR: 12fec8, 42703c, 42703d
It can be found that the results of the ARR address (left value) are consistent with the address of the first element in the array, while the PTR variable value (Right Value) is consistent with the address of the first element in the array.
Therefore, to reference the elements in an array, both c = arr [I] and c = PTR [I] can retrieve the I element in the corresponding array. Note that the two operations are completely different:
C = arr [I]; C = PTR [I];
1: Get the content of the address 12fec8, that is, 42703c
1. Add the I value to 12fed4. 2. Add the I value to 42703c.
2. Content of address (12fed4 + I) 3: content of address (42703c + I)
Conclusion: Although c = arr [I] and c = PTR [I] accomplish the same function in the same form, they cannot be mixed. Note the original declaration method of the array. If the original declaration is an array, the reference to its elements should be in the array format, and vice versa.
File 1:
Int array [100];
File 2:
Extern int * array;
Array [50] = 3; // do you know why this sentence is wrong?
--------------------------------------- Section 3 array and pointer are the same ----------------------------------
In three cases, the array name is regarded as a pointer.
1 "array name in expression" is pointer
Int A [10], * P, I;
P = A; // here
2. the array subscript is the pointer offset.
The functions of the following statements are the same, but the implementation process is different (section 2 ):
A [I] = 0;
P [I] = 0;
* (P + I) = 0;
3. the array name in the function parameter is treated as a pointer to the first element.
The following three function declarations are equivalent:
My_function (int * P ){...}
My_function (int p []) {...}
My_function (int p [100]) {...}
The call to the my_function function is valid no matter whether the real parameter is an array or a pointer.
-------------------------------------------- Section 4 Multi-dimensional array -------------------------------------
First, understand a simple multi-dimensional array:
Int main ()
{
Int cot [2] [3] [5];
INT (* P) [3] [5] = cot; // do not forget that "the array name in the expression" is the pointer.
INT (* r) [5] = cot [1];
Int * t = cot [1] [2];
Int u = cot [1] [2] [3];
Return 0;
}
According to the array subscript rules, it is not difficult to understand that the compiler will resolve cot [I] [J] [k] To (* (COT + I) + J) + k ). In addition, the layout of multi-dimensional arrays in the memory is linear, therefore, we can obtain cot [I] [J] [k] Through calculation * (& cot + I * 3*5 + J * 5 + k.
Another method is to use a pointer array or pointer. This method is flexible and supports dynamic allocation of multi-dimensional arrays.
Char * pea [4];
Char ** pea;
You can still use pea [I] [J] to reference the variables and the above memory location calculation method (Note whether the continuous linear memory layout is satisfied ). However, it should be noted that initialization of such variables is a little tricky, because it is necessary to ensure that the pointer is valid in the subsequent use process. The common method is loop malloc.
For (j = 0; j <4; j ++)
Pea [J] = malloc [6];
Or malloc a whole piece of data at a time, and then point the pointer to each region in a loop:
Malloc (row * column * sizeof (char ));
Finally, I came to two subprograms in my yuvlib and understood the pointer to pass through.
**************************************** ********************************
* \ Brief
* Allocate 2D memory array-> unsigned char array2d [rows] [columns]
*
* \ Par output:
* Memory size in bytes
**************************************** ********************************/
Int get_mem2d (byte *** array2d, int rows, int columns)
{
Int I;
If (* array2d = (byte **) malloc (rows * sizeof (byte *) = NULL)
Exit (2 );
If (* array2d) [0] = (byte *) malloc (columns * Rows * sizeof (byte) = NULL)
Exit (2 );
For (I = 1; I <rows; I ++)
(* Array2d) [I] = (* array2d) [I-1] + columns;
Return rows * columns;
}
/*!
**************************************** ********************************
* \ Brief
* Free 2D memory array
* Which was alocated with get_mem2d ()
**************************************** ********************************
*/
Void free_mem2d (byte ** array2d)
{
If (array2d)
{
If (array2d [0])
Free (array2d [0]);
Else exit (6 );
Free (array2d );
} Else
{
Exit (6 );
}
}