Detailed explanation of pointers (from basics to entry)

1. What is a pointer?

In computer science, a pointer is an object in a programming language that points directly to a value stored in another location in the computer's memory, using an address. Since the required variable unit can be found via the address, it can be said that the pointer points to this variable unit. Therefore, the address is visually called a pointer. It means that it can find the memory unit with its address. From another aspect, the pointer is a variable used to store the address (encoding) of the memory unit. The address uniquely identifies a memory space.

This can be illustrated by the following C code:

#include<stdio.h>
int main()
{
    
    
    int a=10;//在内存中开辟一块空间
    int *p=&a;//取出a的地址,将a的地址存放在p变量中,p就是一个指针变量
    return 0}

ps: The values ​​stored in pointers are treated as addresses. On a 32-bit platform, a pointer variable occupies 4 bytes, and on a 64-bit platform, a pointer variable occupies 8 bytes.

2. The meaning of pointer types

Since the size of pointer variables is fixed, why are there various pointer types?

1. The pointer type determines the size of the space that can be accessed when the pointer is detached for reference operations.
The following is an example:

When the pointer type is character type, there is the following C code
Insert image description here
By observing the address change of a, it can be seen that when the pointer of char type is dereferenced and its corresponding value is changed, , two bytes of content can be changed (only two bytes of space can be accessed).

When the pointer type is an integer, there is the following C code
Insert image description here
By observing the change of the address of a in the memory, it can be seen that the pointer of type int is dereferenced and its correspondence is changed. When the value is , four bytes of content can be changed (four bytes of space can be accessed).

Summary: The type of a pointer determines how much authority you have when dereferencing the pointer. For example, the pointer dereference of char * can only access one byte, while the pointer dereference of int * can access four bytes, and the pointer dereference of double * can access eight bytes.

2. The type of pointer determines the step size of pointer addition and subtraction of integers.

Observe the following C code and its running results:
Insert image description here
It is not difficult to find that after the integer pointer variable (pa) + 1, the address jumps from C4 to C8, jumping backward by 4 bytes (an integer); after the character pointer variable (pc) is +1, the address jumps from C4 to C5, jumping back 1 byte (one character); similarly, after the double pointer variable +1 , the address should jump backward 8 bytes.

Summary: The pointer type determines how far (distance) the pointer moves one step forward or backward.

We can deepen our understanding through the following examples

Example: Given the array int arr[10]={0}, use pointers to set all array elements to 1

#include<stdio.h>
int main()
    {
    
    
    int arr[10]={
    
    0};
    int* p=arr;//数组名表示首元素地址
    int i=0;
    for(i=0;i<10;i++)//将各数组元素全部置为1
    {
    
    
        *(p+i)=1;//p为int类型的指针,每加一向后跳跃一个整形(4个字节)
    }
    for(i=0;i<10;i++)//打印输出
    {
    
    
        printf("%d ",arr[i]);
    }
    return 0;
    }

If p is a pointer of type char, it can also be implemented through the following code

#include<stdio.h>
int main()
    {
    
    
    int arr[10]={
    
    0};
    char* p=arr;//数组名表示首元素地址
    int i=0;
    for(i=0;i<10;i++)//将各数组元素全部置为1
    {
    
    
        *(p+4*i)=1;//p为char类型的指针,每加一向后跳跃一个字符(1个字节),题设数组元素为整形(4个字节),应该加上4*i
    }
    for(i=0;i<10;i++)//打印输出
    {
    
    
        printf("%d ",arr[i]);
    }
    return 0;
    }

3. Wild pointer

**

(1) Concept

**

A wild pointer means that the position pointed by the pointer is unknown (random, incorrect, and has no clear limit).

**

(2) Causes of wild pointers

**

1. The pointer is initialized

Such as the following C code

#include<stdio.h>
int main()
{
    
    
    int* p;//局部指针变量未初始化,默认为随机值
    *p=10;
    return 0;
}

2. Pointer out-of-bounds access

Such as the following C code

#include<stdio.h>
int main()
{
    
    
   int arr[10]={
    
     0 };
   int* p=arr;//数组名代表首元素地址
   int i=0;
   for(i=0;i<12;i++)
   {
    
    
       *(p++)=i;
       //数组元素个数为10,当i>9时,指针指向的范围超过了数组arr的范围,此时p就是野指针
   }
   return 0;
}

3. The pointer points to the released space

Such as the following C code

#include<stdio.h>
int* test()
{
    
    
    int a = 10;
    //a为局部变量,函数开始时创建,函数结束时销毁
    return &a;
}
int main()
{
    
    
    int* p = test();
    *p = 20;
    //此时p指向的空间已销毁(被释放),不属于当前程序,此时指针p就为野指针
    return 0;
}

(3) How to avoid the appearance of wild pointers

1. Pointer initialization
2. Pay attention to whether the pointer is out of bounds
3. When the pointer points to the released space, it is set to NULL (null pointer)
4. The validity of pointers should be checked before use

4. Pointers and Arrays

(1) Pointers and arrays

The array name represents the address of the first element

Insert image description here
Note: The following two situations are exceptions
1. &array name (such as &arr)
The array name is not the address of the first element. The name (arr) represents the entire array, &array name (&arr) represents the address of taking out the entire array
Insert image description here
arr—>arr+1, jumping back 4 bytes a>
&arr—>&arr+1, jumps back 40 bytes (hexadecimal A20 minus 9F8 is 28, converted to decimal is 40)

2. sizeof (array name), such as sizeof(arr)
The array name (arr) represents the entire array, and sizeof (arr) calculates the size of the entire array

(2) Pointer array

Pointer arrays are essentially arrays. By analogy with integer arrays (which store integers) and character arrays (which store character types), we can see that pointer arrays are used to store pointers.
Insert image description here

(3) Array pointer

For detailed explanation, see the following code

Insert image description here

The usage of array pointers is as follows

#include<stdio.h>
void print2(int (*p)[5], int x, int y)
//第一个形参int (*p)[5]为数组指针,存放的是第一行元素构成的一维数组的地址
{
    
    
    int i = 0;
    int j = 0;
    for (i = 0; i < x; i++)
    {
    
    
        for (j = 0; j < y; j++)
        {
    
    
            printf("%d ", *(*(p + i)+j));
            /* 
            p的类型为数组指针,指向为一个一维数组的地址,p+1表示向后跳过一个数组大小,p + i表示向
            后跳过i行,假设二维数组每一行分别代表一个一维数组,则 *(p + i)表示对应的一维数组的数
            组名,而数组名代表该一维数组首元素的地址。该数组为整形数组,+j表示向后跳跃j个整形的大
            小,得到该一维数组各个元素的地址,即*(p + i)+j)表示二维数组中各个元素的地址,再通过解
            引用操作得到各个元素的值,即*(*(p + i)+j)表示二维数组每个元素的值
            */
            
        }
        printf("\n");
    }
}
int main()
{
    
    
    int arr[3][5] = {
    
     {
    
    0,1,2,3,4},{
    
    1,2,3,4,5},{
    
    2,3,4,5,6} };
    print2(arr, 3, 5);
    //在二维数组中,数组名表示第一行数组的地址(可看成一个一维数组的地址)
    return 0;
}

Through the study of pointer arrays and array pointers, we should understand the meaning of the following code
int arr[5]
(a five-element Integer array)
int *arr[5]
(pointer array, the array contains five elements, each element type is int *)< a i=5> int ( * arr)[5] (array pointer, pointing to an array with five elements) int( * arr[10] )[5] (is an array. The array has ten elements. Each element is an array pointer. The array pointed to by the array pointer has five elements. Each element is of type int. )



5. Function pointers

As the name suggests, a function pointer is a pointer to a function, which is used to store the function address.

The representation method of function pointer
Insert image description here
can be understood through the following code

#include<stdio.h>
int Add(int x, int y)
{
    
    
    return x + y;
}
int main()
{
    
    
    int a = 0;
    int b = 0;
    int (*p)(int, int) = Add;//定义一个函数指针
    printf("%d\n", (*p)(10, 20));//通过函数指针调用函数
    //输出结果为30
    return 0;
}
#include<stdio.h>
void Print(char* str)
{
    
    
    printf("%s\n", str);
}
int main()
{
    
    
    void (*p)(char*) = Print;//定义一个函数指针
    (*p)("Hello World");//通过函数指针调用函数
    return 0;
}

Example:
Explain the following code

//解释以下代码
void(*fun(int, void(*)(int)))(int);
        //fun是一个函数声明
        //fun函数的参数有两个,第一个为int类型,第二个为函数指针类型,该函数指针指向的函数参数类型为int,返回类型为void
        //fun函数的返回类型也是一个指针函数,该指针函数指向的函数的参数为int,返回类型为void(空)
//上述代码可通过typedef关键字进行简化,简化代码如下:
    typedef void(*fun_t)(int);//将该函数指针类型创建别名fun_t
    fun_t(fun(int, fun_t));

6. Array of function pointers

The function pointer array is essentially an array, and each element of the array is the address of a function.

#include<stdio.h>
int Add(int x, int y)
{
    
    
    return x + y;
}
int Sub(int x, int y)
{
    
    
    return x - y;
}
int Mul(int x, int y)
{
    
    
    return x * y;
}
int Div(int x, int y)
{
    
    
    return x / y;
}
int main()
{
    
    
    int(*p[4])(int, int) = {
    
     Add,Sub,Mul,Div };//定义一个函数指针数组
    int i = 0;
    for (i = 0; i < 4; i++)
    {
    
    
        printf("%d\n", p[i](10, 5));//循环逐个调用函数
    }
    return 0;
}

Insert image description here

Purpose of function pointer array:Transfer table
Example: Implementation of calculator

#include<stdio.h>
void menu()
{
    
    
    printf("**********************\n");
    printf("******   1.Add  ******\n");
    printf("******   2.Sub  ******\n");
    printf("******   3.Mul  ******\n");
    printf("******   4.Div  ******\n");
    printf("******   0.exit ******\n");
    printf("**********************\n");
}
int Add(int x, int y)
{
    
    
    return x + y;
}
int Sub(int x, int y)
{
    
    
    return x - y;
}
int Mul(int x, int y)
{
    
    
    return x * y;
}
int Div(int x, int y)
{
    
    
    return x / y;
}
int main()
{
    
    
    int input = 0;
    int x = 0;
    int y = 0;
    int (*pfarr[])(int, int) = {
    
    0, Add,Sub,Mul,Div };
    //pfarr为一个函数指针数组—转移表,通过函数指针数组下标转到对应的函数
    do
    {
    
    
        printf("请输入你的选择:\n");
        scanf_s("%d", &input);
        if (input >= 1 && input <= 4)
        {
    
    
            printf("请输入两个数:\n");
            scanf_s("%d %d", &x,&y);
            printf("%d\n", pfarr[input](x, y));
        }
        else if (input == 0)
        {
    
    
            printf("退出!\n");
        }
        else
        {
    
    
            printf("输入错误,请重新输入\n");
        }
    } while (input);
    return 0;
}

7. Function pointer array pointer

[Function pointer array] Pointer, pointer, pointing to an array of function pointers

    int (*pf)(int, int);//函数指针
    int(*pfarr[5])(int, int);//函数指针数组
    int(*(*pparr)[5])(int, int)=&pfarr;//函数指针数组指针,指向【函数指针数组】的指针
    //所指向的函数指针数组有5个元素,每个元素为一个函数指针,类型为int(*)(int,int)

Guess you like

Origin blog.csdn.net/weixin_75094128/article/details/129249462