Language in-depth understanding of pointers (very detailed) (3)

Understanding array names

In the previous chapter, when we used pointers to access the contents of an array, we had this code:

int arr[10] = {
    
    1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];

Here we use &arr[0] to get the address of the first element of the array, but in fact the array name is actually the address, and it is the address
of the first element of the array. Let's do a test.

#include <stdio.h>
int main()
{
    
    
int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p\n", arr);
return 0;
}

The output results are as follows:
insert image description here
We find that the array name and the address of the first element of the array print exactly the same result, and the array name is the address of the first element (the first element) of the array
.
But let’s look at another code

#include <stdio.h>
int main()
{
    
    
int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", sizeof(arr));
return 0;
}

If it is the address of the first element, then sizeof(arr) should also be the size of the first element, which is 4 or 8, but the result is 40.

In fact, the address of the first element is correct, but the sizeof(arr) here is the address of the entire array (just the two addresses are the same, but there are still differences like sizeof(arr)). The following are two exceptions:

• sizeof (array name), put the array name separately in sizeof. The array name here represents the entire array, and the size of the entire array is calculated. The unit is bytes.

• &array name, the array name here represents the entire array, and the address of the entire array is taken out (there is a
difference between the address of the entire array and the address of the first element of the array)

In addition, wherever an array name is used, the array name represents the address of the first element.
Let’s look at another piece of code

#include <stdio.h>
int main()
{
    
    
int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
printf("&arr[0] = %p\n", &arr[0]);
printf("&arr[0]+1 = %p\n", &arr[0]+1);
printf("arr = %p\n", arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr = %p\n", &arr);
printf("&arr+1 = %p\n", &arr+1);
return 0;
}

The running results are as follows:
insert image description here
We can see that the difference between &arr[0] and arr+1 is 4 bytes compared with the original address, and the difference after &arr+1 is 40 bytes, which is exactly the size of the entire array element, so we It can be inferred that when taking the entire element address, we +1 is to move the size of the entire array.

Access arrays using pointers

#include <stdio.h>
int main()
{
    
    
int arr[10] = {
    
    0};
//输⼊
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
//输⼊
int* p = arr;
for(i=0; i<sz; i++)
{
    
    
scanf("%d", p+i);
//scanf("%d", arr+i);//也可以这样写
}
//输出
for(i=0; i<sz; i++)
{
    
    
printf("%d ", *(p+i));
}
return 0;
}

After understanding this code, let's try it again. If we analyze it again, the array name arr is the address of the first element of the array, which can be assigned to p. In fact, the array names arr and p are equivalent here. Then we can use arr[i] to access the elements of the array. Can p[i] also access the array?

#include <stdio.h>
int main()
{
    
    
int arr[10] = {
    
    0};
//输⼊
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
//输⼊
int* p = arr;
for(i=0; i<sz; i++)
{
    
    
scanf("%d", p+i);
//scanf("%d", arr+i);//也可以这样写
}
//输出
for(i=0; i<sz; i++)
{
    
    
printf("%d ", p[i]);
}
return 0;
}

In line 18, replacing * (p+i) with p[i] can also be printed normally, so essentially p[i] is equivalent to *(p+i).
In the same way, arr[i] should be equivalent to *(arr+i). When the compiler processes the access to the array element, it is also converted into the address of the first element + the offset to find the address of the element, and then dereferences it for access
. In
fact, when the computer processes it, it becomes in the form of *(arr+i).
This is actually similar to the commutative property of addition
arr[i]= (arr+i)= (i+arr)=i[arr]

The essence of one-dimensional array parameter passing

#include <stdio.h>
void test(int arr[])
{
    
    
int sz2 = sizeof(arr)/sizeof(arr[0]);
printf("sz2 = %d\n", sz2);
}
int main()
{
    
    
int arr[10] = {
    
    1,2,3,4,5,6,7,8,9,10};
int sz1 = sizeof(arr)/sizeof(arr[0]);
printf("sz1 = %d\n", sz1);
test(arr);
return 0;
}

insert image description here
We found that the number of elements of the array was not correctly obtained inside the function.
The array name is the address of the first element of the array ; then when the array parameter is passed, the array name is passed, which means that in essence, the array parameter is passed The address of the first element of the array
. Therefore, the function parameter part should theoretically use a pointer variable to receive the address of the first element. Then inside the function we write sizeof(arr) to calculate the size of an address (unit bytes) rather than the size of the array (unit bytes) . Precisely because the parameter part of the function is essentially a pointer, there is no way to find the number of array elements inside the function .

void test(int arr[])//参数写成数组形式,本质上还是指针
{
    
    
printf("%d\n", sizeof(arr));
}
void test(int* arr)//参数写成指针形式
{
    
    
printf("%d\n", sizeof(arr));//计算⼀个指针变量的⼤⼩
}
int main()
{
    
    
int arr[10] = {
    
    1,2,3,4,5,6,7,8,9,10};
test(arr);
return 0;
}

insert image description here
insert image description here
The running results also verify that the essence of passing parameters in a one-dimensional array is a pointer.
Summary: When passing parameters in a one-dimensional array, the formal parameter part can be written in the form of an array or in the form of a pointer.

secondary pointer

Pointer variables are also variables, and if they are variables, they have addresses.
Therefore, the secondary pointer is the address where the primary pointer can be stored. (When I was learning secondary pointers, I felt a bit like a composite function in mathematics. There is a function inside the function.)
Let's take a look at a code

#include<stdio.h>
int mian()

{
    
    
int a=10;
int *pa=&a;
int **ppa=&pa;
return 0;
}

Let's analyze this code.
Int p represents p as a pointer variable, which stores the address of a, and the corresponding a type is an integer type, so there is an int in front of pa.
The int * in int **p means that the type of pa is a pointer variable, so int is used
to represent pa, and the second * means that ppa is a pointer variable, and the address of pa is stored, which is
useful for secondary pointer operations. :
*ppa By dereferencing the address in ppa, what is found is pa. *ppa actually accesses pa.

int b = 20;
*ppa = &b;//等价于 pa = &b

*ppa first finds pa through *ppa, and then dereferences pa: *pa, then what is found is a

**ppa = 30;
//等价于*pa = 30;
//等价于a = 30

array of pointers

Is an array of pointers a pointer or an array?
Let's make an analogy: an integer array is an array that stores integers, and a character array is an array that stores characters. What about pointer arrays? is an array of pointers.
We can see that expressions like (###)(xxx), ### is the stored element, and xxx is the storage method. Each
insert image description here
element of the array pointer is used to store the address (pointer) (( Array) (pointer) is to store the array through pointer)
as shown below:
insert image description here
Each element of the array pointer is an address and can point to an area.

Pointer array simulates two-dimensional array

#include <stdio.h>
int main()
{
    
    
int arr1[] = {
    
    1,2,3,4,5};
int arr2[] = {
    
    2,3,4,5,6};
int arr3[] = {
    
    3,4,5,6,7};
//数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中
int* parr[3] = {
    
    arr1, arr2, arr3};
int i = 0;
int j = 0;
for(i=0; i<3; i++)
{
    
    
for(j=0; j<5; j++)
{
    
    
printf("%d ", parr[i][j]);
}
printf("\n");
}
return 0;
}

Let’s take a look at the running results.
insert image description here
This is the running result of a two-dimensional array.
insert image description herearr[i] is the element accessing the parr array. The array element found by parr[i] points to an integer one-dimensional array. parr[i][j] is the integer
elements in a one-dimensional array.
The above code simulates the effect of a two-dimensional array. In fact, it is not a completely two-dimensional array, because each row is not continuous (in fact, it is because when inserting the array, it is not the same array, so I don’t know how much separation there is in the middle. bytes)

insert image description here

Guess you like

Origin blog.csdn.net/2301_79178723/article/details/132648622