Comprehensive analysis of C array

Comprehensive analysis of C array

Array name

The value of the array name is a pointer constant, that is, the address of the first element of the array Its type depends on the type of array element

There are only two situations where array names are not represented by pointer constants-------

① sizeof (array name), calculate the size of the whole array. There is a separate array name inside sizeof, and the array name represents the whole array Sizeof returns the length of the entire array

② & array name, the address of the array is taken out& Array name, which represents the whole array Taking the address of an array name produces a pointer to the array

//Code understanding
int a   //a is an integer
int b[10]  //b is an integer array with a length of 10. The array name b is the address of the int type of the first element of the array, that is, a pointer int *p pointing to the integer
int c[3][6]//c is a two-dimensional array with 3 rows and 6 columns. The array name c is the address of the first element of the array of type int [6], that is, a pointer int (*p)[6] pointing to the array
//Understanding of constants
p=&arr[0]  ==   p=arr    
arr[5]     ==   *(arr+5)   == *(p+5)
//Note that in the + + operator, p + + can be implemented, but arr + + cannot, because the array name arr is a pointer constant
 

Multidimensional arrays are also stored continuously in memory! Therefore, multi - dimensional array parameters can actually be received with a first - level pointer But never use a two-dimensional pointer to receive The details will be explained later

Understanding of multidimensional array: the implementation box represents the three elements of the first dimension, and the dotted line is used to divide the six elements of the second dimension,

The value of a dimension group name is a pointer constant. Its type is "pointer to element type", which points to the first element of the array Multidimensional arrays are almost as simple The only difference is that the multidimensional array * * the first dimension element is actually another array**

For example, int c [3] [6] can be regarded as a one-dimensional array containing three elements, but each element contains exactly six integer elements

The value of array name c points to the address of its first element, that is, a pointer to an array containing 10 integer elements, that is, c [6]

When the array name pointer operation is performed, the pointer will skip the size of the first element, that is

	//Code example
	int mat[3][6]; //Define a two-dimensional array
	mat[1][5]  //Access the elements in the first row and fifth column of a two-dimensional array
    *(mat+1)  // A pointer to the second row of the array is equivalent to mat[1]  
    *(mat+1)+5  //It is a pointer Point to the 6th element in line 1, i.e. & mat [1] [5]
    *(*(mat+1)+5)  // Completely equivalent to a[1][5]       
    

subscript

Except for priority, subscript reference and indirect access are exactly the same. Where subscripts are used, equivalent pointers can be used instead For example, the following two expressions are equivalent

  array[i];
  *(array+i);
//Even the following expression is legal, but it is not recommended because it is too unreadable
 2[array];
*(2+(arry));//Equivalent conversion
*(array+2);//Equivalent conversion

The efficiency of the pointer is sometimes more efficient than that of the subscript, but the improvement of efficiency is minimal. I won't elaborate here. Interested bosses can read the book < < C and pointer > >, and most of the content of this article is also drawn from the book

Pointer array

Pointer variables are very similar to other variables except types Just as you can create an integer array, you can also declare a pointer array for example

int *api[10];

To clarify this complex statement, we assume that it is an expression and evaluate it

Subscript reference takes precedence over indirect access, so in this expression, execute subscript reference first So the api is some kind of array (by the way, it contains 10 elements) After getting an array element, the indirect access operator is executed immediately This expression has no other operators, so its result is an integer value

So what exactly is an api? After performing an indirect access operation on an element of the array, we get an integer value, so the api must be an array, and its element type is a pointer to an integer

//Code example
char const *keyword[]={
    "good",
    "morning",
    "afterno",
    "evening",
    NULL        
};
int sz=sizeof(keyword)/sizeof(keyword[0]) //Count the number of elements in the array,
    //sz=sizeof(keyword) calculates the bytes occupied by the whole array, and sizeof(keyword[0]) calculates the bytes occupied by each element of the array
    //Pay special attention to the type char * of keyword[0], that is, the string constant, which accounts for 4 bytes by default in 32 bits
    
    
    
//Comparison code
    char const keyword[][10]={
    "good",
    "morning",
    "afternoom",
    "evening",
    NULL        
};
 //Although the number of array elements is the same, if defined in this way,
//However, sizeof(keyword[0]) calculates that the bytes occupied by each element of the array are the second dimension of the array, that is, char [10] accounts for 10 bytes
//This creates a waste of space

Therefore, people tend to prefer the pointer array scheme

Array parameters

One dimensional array parameter transfer

Through learning, we should now clearly know that the value of the array is an address pointing to the first element of the array, so it is easy to understand that a copy of the pointer is passed to the function at this time

Therefore, array parameters can be declared as arrays or pointers Note: these two declarations are equal only when they are formal parameters of a function

//Code example
int arr[10];
void test(int arr[])//
{}
void test(int arr[10])//In fact, since the array parameter is only the address of the array, c does not really care about the length of the array when passing the parameter, nor can it know the length of the array through the parameter
{}
void test(int *arr)//
{}
//All three statements are acceptable

Multidimensional array parameter transfer

conventional method

The multidimensional array name as a function parameter is passed in the same way as the one-dimensional array name - what is actually passed is a pointer to the first element of the array

However, the difference between the two is that each element of the multidimensional array itself is another array. The compiler needs to know its dimension so that the function subscript expression can be evaluated

Summary: when a multidimensional array name is passed to a function as a parameter, its formal parameter design can only omit the first dimension, so that the compiler can calculate

Remember: never declare an array parameter as a secondary pointer

//Code example
int arr[3][5];
void test(int (*arr)[5]);
void test(int arr[][5]);

//error code 
void test(int **arr);//This example declares arr as a pointer to an integer pointer, which is not the same thing as a pointer to an integer array

Special method (flattening the array)

Although the compiler may give warnings in this way, the essence of each element of a multidimensional array is its basic data type, and the multidimensional array is also stored continuously in memory, so we can directly declare it as a primary pointer pointing to its basic data type as a formal parameter to receive its address. This technique is called squashing array,

If you need to pass a two-dimensional array to the function and don't want to give the length of the second dimension in the function prototype, you can use this method

int arr[3][5];
void test(int *arr,int row,int col); //Receive using one-dimensional pointer
*(Mat+(i*col)+j) ===Mat[i][j]	//Skip to specified array element + row
				//ps although the compiler and the book may not recommend this method, I think this method is more convenient as long as you master the relationship between pointer and array
//Code example
//There is a number matrix. Each row of the matrix is increasing from left to right, and the matrix is increasing from top to bottom. Please write a program to find out whether a number exists in such a matrix.
//Requirement: the time complexity is less than O(N);

//conventional method 
int findnum(int a[][3], int x, int y, int f) //The type of the first parameter needs to be adjusted
{
	int i = 0, j = x - 1; //Traverse from the top right corner

	while (j >= 0 && i < y)
	{
		if (a[i][j] < f) //Older than me
		{
			i++;
		}
		else if (a[i][j] > f) //Left when I was younger than me
		{
			j--;
		}
		else
		{
			return 1;
		}
	}
	return 0;
}
//Special method (squash array)
int search(int *Mat ,int Des , int row, int col){
	int i = 0, j = (col - 1);			//Start at the top right corner
	while (j >= 0 && i < row){
		if( *(Mat+(i*col)+j)<Des){			//*(Mat+(i*col)+j) is equal to Mat[i][j]
			i++;
		}
		else if (*(Mat+(i * col) + j) > Des){
			j--;
		}
		else return 1;
	}
	return 0;
}
//Test function
int main(){
	int mat[4][5] = { { 1, 2, 3,4,5 },
						{5,6,7,8,9},
					{10,11,12,13,14},
					{15,16,17,18,19} };
	if (search(mat , 19, 4, 5)) printf("yes\n");
	else printf("no\n");



	return 0;
}

Supplementary picture understanding:

Understanding of array pointer:

Understanding of pointer array:

Understanding of multidimensional array and flattened array:

Keywords: C pointer array

Added by Kardall on Thu, 24 Feb 2022 12:48:48 +0200