C pointer 4: pointers and arrays, and c pointer Arrays
Arrays are the basic data structures built in C. array representation and pointer representation are closely related. A common mistake is that arrays and pointers are completely interchangeable. Although array names can be used as pointers, array names are not pointers. One of the differences between arrays and pointers is that although the array name can return an array address, the name cannot be the target of the value assignment operation.
Overview
An array is a continuous set of homogeneous elements that can be accessed using indexes. The elements of the array are adjacent to each other in the memory, and the elements are of the same type. The length of the array is fixed. The realloc function and the variable-length array provide the array technology to cope with the length change.
A one-dimensional array is a linear structure that uses an index to access members. Depending on the memory model, the length of the array may be different.
int vector[5];
The array name only references a piece of memory, and the number of bytes allocated to the array is obtained by using the sizeof operator for the array. To know the number of elements in an array, you only need to divide it by the element length.
int vector[5];printf("vector is %p\nsize is %d\n", &vector, sizeof(vector));//vector is 0xbffb8c08//size is 20
You can use a BLOCK statement to initialize a one-dimensional array.
int vector[5] = {1,2,3,4,5};
Declare a two-dimensional array. The two-dimensional array can be used as an array, and only one subscript is used to access the two-dimensional array to obtain the corresponding row pointer.
int matrix[2][3] = {{1,2,3},{4,5,6}};printf("0 is %p\n1 is %p\n", &matrix[0], &matrix[1]);//0 is 0xbf984044//1 is 0xbf984050
We can see that the two addresses are exactly 12 bytes apart, that is, the length of a row in the matrix array.
Assign the array address to the pointer.
int* pv = vector;
Note that this write method is equivalent to & vector [0], which is different from & vector, which is the pointer of the returned entire array. One is an array pointer and the other is an integer pointer. the pointer types are different. Pv actually represents an address. * (pv + I) is equivalent to pv [I]. The former is calledPointer RepresentationThe latter is calledArray Representation.
printf("pv[0] is %d\n*(pv+1) is %d\n ",pv[0],*pv);//pv[0] is 1//*(pv+1) is 1
The pv pointer contains the address of a memory block. Square brackets indicate that the addresses contained in the pv will be taken out, the index I will be added using the pointer arithmetic operator, and then the new address will be introduced to return its content. Adding an integer to the pointer is actually the product of the integer and the length of the data type. This applies to the array name as well. * (pv + 1) it is equivalent to * (vector + 1. Therefore, the array representation can be understood as the "offset and dereference" operation. The results of the vector [I] And * (vector + I) methods are the same. They are slightly different in implementation and can be ignored. Note that the pointer can be used as the left value, but the array name cannot be used as the left value. vector = vector + 1 is incorrect.
One-dimensional array
If you allocate memory from the heap and assign the address to a pointer, you can certainly use the subscript for the pointer and treat the memory as an array. You can use the realloc function to adjust the length of an existing array created with malloc. C99 supports variable-length arrays, but variable-length arrays can only be declared within the function. Therefore, if the life cycle of the array needs to be longer than the function, or you do not use C99, you can only use realloc.
The following function accepts user input and uses the realloc function to dynamically apply for the required memory. Press enter to end the input.
char* getLine(void){const size_t sizeIncrement = 10;char* buffer = malloc(sizeIncrement);char* currentPosition = buffer;size_t maximumLength = sizeIncrement;size_t length = 0;int character;if(currentPosition == NULL){return NULL;}while(1){character = fgetc(stdin);if(character == '\n'){break;}if(++length >= maximumLength){maximumLength += sizeIncrement;char* newBuffer = realloc(buffer,maximumLength);if(newBuffer == NULL){free(buffer); return NULL;}currentPosition = newBuffer + (currentPosition - buffer);buffer = newBuffer;}*currentPosition++ = character;}*currentPosition = '\0';printf("buffer is %s\n", buffer);return buffer;}getLine();
Passing a one-dimensional array as a parameter to a function actually uses a value to pass the address of the array. We need to tell the length of the Function Array. Otherwise, the function has only one address and does not know how long the array actually exists. The length of a string can be determined by NUL characters. Some arrays cannot be determined.
Declaring a pointer to an array is different from an array or an array pointer. The pointer to the array is an element pointing to the array subscript 0. The pointer array is an array with the element as the pointer, And the array pointer is an array type pointer.
Int vector [2] = {1, 2}; int * pv1 = vector; // pointer to the array int * pv2 [2]; // pointer array, you can use a loop to allocate memory int (* pv3) [2] for each pointer; // an array pointer.
Now let's differentiate the array representation and pointer representation in the pointer array.
int* array[5];array[0] = (int*) malloc (sizeof(int));*array[0] = 100;*(array+1) = (int*) malloc (sizeof(int));**(array+1) = 200;
Here, array [1] and * (array + 1) are equivalent. Actually, they are all pointer types. The malloc function is used to allocate memory for the pointer on the heap, And the cited pointer is used to assign values to the data, therefore, ** (array + 1) is not difficult to understand. A * solution gets a pointer, and the data is obtained after the pointer is parsed. [] brackets have already explained that, it is equivalent to an operation to get the address and add the index. Of course, you can also use array [0] [0] instead of * array [0].
Pointers and multi-dimensional arrays
You can think of a part of a multi-dimensional array as a sub-array, for example, each row of a two-dimensional array as a one-dimensional array. The array is stored in row-column order, and the memory address of the first element in the second row follows the last element in the first row.
Int matrix [2] [3] = {1, 2, 3}, {4, 5, 6}; int (* pmat) [3] = matrix; // 3 is the number of columns in the two-dimensional array printf ("size of pmat [0] is % d \ n", sizeof (pmat [0]); // size of pmat [0] is 12
We can see that the length of the first element of the array pointer is 12 bytes, that is, the length of the first row. To access the first element of the first line, use pmat [0] [0. Array [I] [j] is equal to array + I * sizeof (row) + j * sizeof (element ). Sizeof (row) is the total size of a row, sizeof (element) is the size of a single element, and array is the address of array [0] [0.
When passing array parameters to a function, you must consider how to pass the dimension of the array and the size of each dimension. The following are two ways to pass a two-dimensional array:
void display2DArray(int arr[][3], int rows){}void display2DArray(int (*arr)[3], int rows){}
Both methods specify the number of rows. If the passed array dimension exceeds two-dimensional, specify the length of other dimensions except the one-dimensional dimension. If you pass an array of array3D [3] [2] [4:
void display3DArray(int (*arr)[2][4], int rows){}
When malloc is used to allocate memory for different sub-arrays of two-dimensional arrays, memory allocation may be discontinuous. This issue does not occur if you use block statements for one-time initialization. There are two strategies to use malloc to allocate continuous memory for two-dimensional arrays. Assume that the two-dimensional array has three rows and four columns. First, allocate all memory 3*4 * sizeof (element) at a time ), then, you can manually calculate the memory address to be accessed by using the method described above to access array [I] [j. The second method is divided into two steps. The first step is to use malloc to allocate a piece of memory to store the pointer to each row of the Two-dimensional array. The second step is to allocate all the memory for the pointer of array [0] [0], and then calculate the positions of array [1] [0] and array [2] [0, assign values to the two key pointers respectively, so that you can use subscript access based on the pointer of each row.
Int rows = 3; int columns = 5; // The first method int * matrixx = (int *) malloc (rows * columns * sizeof (int )); // method 2 int ** matrixy = (int **) malloc (rows * sizeof (int *); matrixy [0] = (int *) malloc (rows * columns * sizeof (int); int I = 1; while (I <rows) {I ++; matrixy [I] = matrix [0] + I * columns ;}
An irregular array is a two-dimensional array with different columns in each row. You can use the composite literal to initialize an irregular array.
(const int) {100}(int [3]) {10, 20, 30}
The access and maintenance of irregular arrays are troublesome, so you should consider it carefully before use.