C language - detailed explanation of pointers (advanced)


Preface: After
learning the basics of C language , you should have a preliminary understanding of pointers. The following advanced content will let us master C language pointers faster.
The concept of pointers:

  1. The pointer is a variable used to store the address, and the address corresponds to the memory space one by one
  2. The size of the pointer is fixed at 4/8 bytes (32-bit platform/64-bit platform)
  3. The pointer has a type, and the type of the pointer determines the step size of the pointer ± integer, and the authority of the pointer dereference operation.
  4. The type of the pointer variable must be consistent with the type of the variable it points to
  5. Pointer variables can only store addresses and cannot be confused with integer variables

1. Character pointer

Character pointer: char*

const char* p="hello word";
the above code means to put the address of the first character h of a constant string into the pointer variable p.

insert image description here

2. Array pointer

Integer Pointer - Pointer to an Integer Variable Char
Pointer - Pointer to a Character Variable Pointer to Array
- Pointer to an Array

2.1 Definition of array pointer

int (*p) [10];
Explanation: p is first combined with *, indicating that p is a pointer variable, and the pointer variable points to an array of 10 integers. Therefore, p is a pointer pointing to an array, also called an array pointer.

2.2 & array name VS array name

What is the difference between & array name and array name?
arr is the name of the array, and the array name indicates the address of the first element of the array
& arr is the address of the array, not the address of the first element of the array
Example 1:

#include <stdio.h>
int main()
{
    
    
    int arr[10] = {
    
     0 };
    printf("%p", arr);
    printf("%p", &arr);
    return 0;
}

insert image description here
Although the addresses are the same, the meanings are different
Example 2:

#include <stdio.h>
int main()
{
    
    
    int arr[10] = {
    
     0 };
    printf("arr=%p\n", arr);
    printf("&arr=%p\n", &arr);
    printf("arr+1=%p\n", arr+1);
    printf("&arr+1=%p\n", &arr+1);
    return 0;
}

insert image description here
From the printed results, we can know that &arr is the address of the array, not the address of the first element of the array.
The address of the array +1 skips the size of the entire array, so &arr+1 skips 40 bytes relative to &arr.
The address of the first element of the array +1 skips the size of one element, so arr+1 is equivalent to skipping 4 bytes in arr.

2.3 Use of array pointers

The array pointer points to the array, and the address of the array is stored in the array pointer.
The use of the array pointer

#include <stdio.h>
void arr1(int arr[][5], int row, int col)
{
    
    
    int i, j;
    for (i = 0; i < row; i++)
        for (j = 0; j < col; j++)
            printf("%d ", arr[i][j]);
    printf("\n");
}
void arr2(int(*arr)[5], int row, int col)
{
    
    
    int i, j;
    for (i = 0; i < row; i++)
        for (j = 0; j < col; j++)
            printf("%d ", arr[i][j]);
    printf("\n");
}
int main()
{
    
    
    int arr[3][5] = {
    
     1,2,3,4,5,6,7,8,9,10 };
    arr1(arr, 3, 5);
    //数组名arr表示数组首元素地址
    //二维数组的首元素地址是二维数组的第一行
    //这里传递的arr,就是第一行的地址,就是一维数组的地址
    //可以用数组指针来接收
    arr2(arr, 3, 5);
    return 0;
}

Printed results
insert image description here

3. Array of pointers

Integer array - an array of integers
Character array - the address of character data
Pointer array - an array of pointers

int* arr1[10];//array of integer pointers
char* arr2[4];//array of primary character pointers
char** arr3[5];//array of secondary character pointers

4. Array parameters and pointer parameters

Setting of function parameters

4.1 One-dimensional array parameter passing

#include <stdio.h>
void test(int* p)//对的
{
    
    }
void test(int arr[10])//对的
{
    
    }
void test(int arr[])//对的
 {
    
    }
void test1(int** arr1)//对的
{
    
    }
void test1(int* arr1[20])//对的
{
    
    }
int main()
{
    
    
    int arr[10] = {
    
     0 };
        int *arr1[20] = {
    
     0 };
        test(arr);
        test1(arr1);
    return 0;
}

4.2 Two-dimensional array parameter passing

#include <stdio.h>
void test(int arr[][5])//形参部分,行可以省略,但是列不可以省略
{
    
    }//对的
void test(int  arr[3][5])
{
    
    }//对的
void test(int (*arr)[5])//数组指针
{
    
    }//对的
void test(int *arr[5])//存放指针的数组
{
    
    }//错的
void test(int arr[][])
{
    
    }//错的
void test(int **arr)
{
    
    }//错的
void test(int *arr)
{
    
    }//错的
int main()
{
    
    
    int arr[3][5] = {
    
    0};
    test(arr);//首元素的地址,一行的地址
    return 0;
}

Summary: The type of the formal parameter and the actual parameter must be the same;
when passing parameters in a two-dimensional array, the design of the function parameter can only omit the first [] number, because for a two-dimensional array, you don’t need to know how many lines there are, but you must know How many elements are there in a row.

4.3 First-level pointer parameter passing

#include <stdio.h>
void test(int* p, int sz)
{
    
    
    int i = 0;
    for (i = 0; i < sz; i++)
        printf("%d ", *(p + i));
}
int main()
{
    
    
    int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
    int* p = arr;
    int sz = sizeof(arr) / sizeof(arr[0]);
    test(p, sz);//一级指针p,传给函数
    return 0;
}
void test(char* p)
{
    
    }
char ch=9’;
char* ptr=&ch;
char arr[]="abcdef";
参数为一级指针的时候接收什么参数
test(&ch);
test(ptr);
test(arr);

4.4 Second-level pointer parameter passing

void test(char** p)
{
    
    }

char n=‘p’;
char* p1=&n;
char** p2=&p1;
char* arr[5];
参数为二级指针的时候接收什么参数
test(&p1);
test(p2);
test(arr);

Five, function pointer

  • If a function is defined in the program, the system will open up a section of storage space for the function code at compile time.
  • The first address of this storage space is called the address of the function , and the function name indicates this address .
  • Since it is an address, we can define a pointer variable to store it. This pointer variable is called a function pointer variable , or function pointer for short .

The form of function pointer definition:
data type specifier (*function name) ([formal parameter list]);
note: the formal parameter list can be omitted.

#include <stdio.h>
void test()
{
    
    
    printf("hehe");
}
int main()
{
    
    
    printf("p\n", test);//函数名是函数的首地址
    printf("p\n", &test);//&函数名也是函数的地址
    return 0;
}

int (*pf) (int, int) = &test;
pf is a function pointer variable
Share two interesting codes

Code 1:
(*(char(*)())0)()
0 is cast to function pointer type
This function at address 0 is called
Code 2:
void(*sig(int, void(*)(int)) ) (int)
sig is a function declaration
The sig function has two parameters, the first parameter type is int, the second parameter type is void (*) (int) function pointer type The function pointed to by the function pointer
has an int type Parameters, the return type is void
can simplify code 2:
typedef void ( * pf ) (int); pf sig(int,pf);

6. Array of function pointers

Store the address of the function in an array, which is called an array of function pointers
Form:

int(*pf[10])();
pf is an array, and the contents in the array are function pointers of type int(*)().
Purpose of array of function pointers: transfer table

example:

#include <stdio.h>
void menu()
{
    
    
    printf("*******************\n");
    printf("**1.加法   2.减法**\n");
    printf("**3.乘法   4.除法**\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;
    int ret = 0;
    int a,  b;
    int (*py[5])(int a, int b) = {
    
     0,add,sub,mul,div };//定义一个函数指针数组,5个元素,每个元素存放一个函数
    do
    {
    
    
        menu();//菜单
        scanf("%d", &input);
        if (input >= 1 && input <= 4)//根据取值范围,进入函数
        {
    
    
            printf("请输入操作数:\n");
            scanf("%d %d", &a, &b);
            ret = (*py[input])(a, b);//调用函数指针数组
            printf("%d\n", ret);
        }
        else if (input == 0)
            ;
        else
            printf("输出错误,请重新输入:\n");
    } while (input);//非零的值就一直循环
}

7. A pointer to an array of function pointers

A pointer to an array of function pointers is a pointer , and the pointer points to an array whose elements are function pointers .

int(*pf)(int,int); //function pointer
int(*p[5])(int,int); //function pointer array
int(*(*pff)[5])(int,int) = &p ; //The address p of the function pointer array
is the pointer to the function pointer array

#include <stdio.h>
void test(const char* str)
{
    
    
    printf("%s\n", str);
}
int main()
{
    
    
//函数指针pf
    void(*pf)(const char*) = test;//pf是函数指针变量
    //函数指针数组pff
    void (*pff[10])(const char* str);//pff是存放函数指针的数组
    pff[0] = test;//函数名是函数的地址,&函数名也是函数的地址
    //指向函数指针数组pff的指针pfff
    void (*(*pfff)[5])(const char*)=&pff;//pfff是指向函数指针数组的指针
    return 0;
}

8. Callback function

A callback function is a function that is called through a function pointer. If you pass a function pointer (address) as a parameter to another function, when this pointer is used to call the function it points to, we say this is a callback function. The callback function is not directly called by the implementer of the function, but is called by another party when a specific event or condition occurs, and is used to respond to the event or condition.
Example:
use the callback function to simulate the implementation of qsort (the way of bubbling)

#include <stdio.h>
//回调函数
int cmp(const void* p1, const void* p2)
{
    
    
    return *(int*)p1-*(int*)p2;
}
void _swap(void* p1, void* p2,  int size)
{
    
    
    int i = 0;
    for (i = 0; i < size; i++)
    {
    
    
        char tmp = *((char*)p1 + i);
        *((char*)p1+i)= *((char*)p2 + i);
        *((char*)p2 + i) =tmp;
    }
}

void bubble(void* ba,int count,int si,int(*cmp)(void*, void*))//函数指针调用的函数,函数指针作为参数传递给另外的函数
{
    
    
    int i = 0, j = 0;
    for (i = 0; i < count - 1; i++)
    {
    
    
        for (j = 0; j < count - 1; j++)
        {
    
    
            if (cmp((char*)ba + j * si, (char*)ba + (j + 1) * si) > 0)
                _swap((char*)ba + j * si, (char*)ba + (j + 1) * si, si);
        }
    }
}
int main()
{
    
    
    int arr[] = {
    
     11,2,32,4,5,61,7,81,9 };
    int i = 0;
    bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), cmp);
    for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
    
    
        printf("%d ",arr[i]);
    }
    printf("\n");
return 0;
}

Guess you like

Origin blog.csdn.net/plj521/article/details/131748490