• C语言_指针进阶(下)



    前言


    一、函数指针数组

    数组是一个存放相同类型数据的存储空间,
    那把函数的地址存放到一个数组中,那这个数组就叫函数指针数组
    提示:以下是代码样例,下面案例可供参考

    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;
    }
    //计算器
    void  menu()
    {
        printf("************************\n");
        printf("*****1. Add 2. Sub *****\n");
        printf("*****3. Mul 4. Div *****\n");
        printf("*****  0. exit  ********\n");
        printf("************************\n");
    }
    
    int main()
    {
        int x = 0;
        int y = 0;
        int ret = 0;
        int input = 0;
        //定义一个函数指针数组
        int (*pfArr[5])(int, int) = { NULL,Add,Sub,Mul,Div };
        //                             0     1   2   3   4
        do
        {
            menu();
            printf("请选择:>\n");
            scanf("%d", &input);
            if (input >= 1 && input <= 4)
            {
                printf("请输入两个操作数:");
                scanf("%d %d", &x, &y);
                ret = pfArr[input](x, y);
                printf("ret = %d\n", ret);
            }
            else if (input = 0)
            {
                printf("退出计算器\n");
            }
            else
            {
                printf("选择错误,重新选择\n");
            }
        } while (input);
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    二、指向函数指针数组的指针

    三. 回调函数

    回调函数就是一个通过函数指针调用的函数,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
    回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时有另外的一方调用的,用于对该事件或条件进行响应。

    四. qsort 函数

    qsort 是标准库函数,用于对数组中的元素进行快速排序。它通过比较两个元素的大小来确定它们的顺序。以下是 qsort 函数的定义:

    void qsort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *));
    
    • 1

    参数说明:

    • base:指向要排序的数组的第一个元素的指针。
    • count:要排序的元素数量。
    • size:每个元素的字节数。
    • compare:一个比较函数,用于比较两个元素的大小。该函数返回一个整数值,指示两个元素的顺序关系。如果返回负数,则表示第一个元素应该排在第二个元素的前面;如果返回正数,则表示第一个元素应该排在第二个元素的后面;如果返回 0,则表示两个元素相等。

    使用 qsort 函数时,需要自定义一个比较函数,根据实际需要对元素进行比较。以下是一个简单的示例:

    #include 
    #include 
    
    int compare(const void *a, const void *b) {
        return (*(int*)a - *(int*)b);
    }
    
    int main() {
        int arr[] = {3, 1, 4, 2, 5};
        int n = sizeof(arr) / sizeof(int);
    
        qsort(arr, n, sizeof(int), compare);
    
        for (int i = 0; i < n; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    输出结果为:1 2 3 4 5,表示数组已经按从小到大的顺序排好了序。qsort 是标准库函数,用于对数组中的元素进行快速排序。它通过比较两个元素的大小来确定它们的顺序。以下是 qsort 函数的定义:

    void qsort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *));
    
    • 1

    参数说明:

    • base:指向要排序的数组的第一个元素的指针。
    • count:要排序的元素数量。
    • size:每个元素的字节数。
    • compare:一个比较函数,用于比较两个元素的大小。该函数返回一个整数值,指示两个元素的顺序关系。如果返回负数,则表示第一个元素应该排在第二个元素的前面;如果返回正数,则表示第一个元素应该排在第二个元素的后面;如果返回 0,则表示两个元素相等。

    使用 qsort 函数时,需要自定义一个比较函数,根据实际需要对元素进行比较。以下是一个简单的示例:

    #include 
    #include 
    
    int compare(const void *a, const void *b) {
        return (*(int*)a - *(int*)b);
    }
    
    int main() {
        int arr[] = {3, 1, 4, 2, 5};
        int n = sizeof(arr) / sizeof(int);
    
        qsort(arr, n, sizeof(int), compare);
    
        for (int i = 0; i < n; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    输出结果为:1 2 3 4 5,表示数组已经按从小到大的顺序排好了序。qsort 是标准库函数,用于对数组中的元素进行快速排序。它通过比较两个元素的大小来确定它们的顺序。以下是 qsort 函数的定义:

    void qsort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *));
    
    • 1

    参数说明:

    • base:指向要排序的数组的第一个元素的指针。
    • count:要排序的元素数量。
    • size:每个元素的字节数。
    • compare:一个比较函数,用于比较两个元素的大小。该函数返回一个整数值,指示两个元素的顺序关系。如果返回负数,则表示第一个元素应该排在第二个元素的前面;如果返回正数,则表示第一个元素应该排在第二个元素的后面;如果返回 0,则表示两个元素相等。

    使用 qsort 函数时,需要自定义一个比较函数,根据实际需要对元素进行比较。以下是一个简单的示例:

    #include 
    #include 
    
    int compare(const void *a, const void *b) {
        return (*(int*)a - *(int*)b);
    }
    
    int main() {
        int arr[] = {3, 1, 4, 2, 5};
        int n = sizeof(arr) / sizeof(int);
    
        qsort(arr, n, sizeof(int), compare);
    
        for (int i = 0; i < n; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    输出结果为:1 2 3 4 5,表示数组已经按从小到大的顺序排好了序。

    五. 数组名的理解 sizeof

    提示:以下是代码样例,下面案例可供参考

    char arr[] = "abcdef";//[a b c d e f \0]
     
        printf("%d\n", sizeof(arr));//7
        //char [7]
        printf("%d\n", sizeof(arr + 0));//arr + 0是首元素的地址   4
        printf("%d\n", sizeof(*arr));//*arr其实就是首元素,1个字节   
        //*arr--> *(arr+0) -- arr[0]
        printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,1个字节   
        printf("%d\n", sizeof(&arr));//&arr是数组的地址,是地址就是4/8个字节
        printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过一个数组的地址,4/8
        printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 4/8
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

     printf("%d\n", sizeof(p));//p是一个指针变量 大小就是4/8
        printf("%d\n", sizeof(p + 1));//p+1是'b'的地址,是地址大小就是4/8个字节
        
        printf("%d\n", sizeof(*p));//*p 就是'a',就是1个字节
        printf("%d\n", sizeof(p[0]));//p[0]--> *(p+0) --> *p  1个字节
    
        printf("%d\n", sizeof(&p));//4/8   &p -- char**
        printf("%d\n", sizeof(&p + 1));//4/8
        printf("%d\n", sizeof(&p[0] + 1));//4/8 , &p[0] + 1得到是'b'的地址 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5.1 数组名的理解(二维数组)

    5.1.1 数组名的理解 strlen

    特点


    提示:以下是代码样例,下面案例可供参考

    int main()
    {
        char arr[] = { 'a','b','c','d','e','f' };
            printf("%d\n", strlen(arr));//因为字符数组arr中没有\0,所以在求字符串长度的时候,会一直往后找,产生的结构就是随机值
            printf("%d\n", strlen(arr + 0));//arr + 0是首元素的地址,和第一个一样,也是随机值
            printf("%d\n", strlen(*arr));//err(错误的写法), arr是数组首元素的地址,*arr就是数组首元素,就是'a'-97
            //strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ASCII码值是97,那就是将97作为地址传参
            //strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了
            //printf("%d\n", strlen(arr[1]));//err
            printf("%d\n", strlen(&arr));//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的,那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计
        
            printf("%d\n", strlen(&arr + 1));//随机值
            printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址。结果也是随机值
    
            return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    char* p = "abcdef";
            //     012345
            
            printf("%d\n", strlen(p));//6
            printf("%d\n", strlen(p + 1));//5
            //printf("%d\n", strlen(*p));//err
            //printf("%d\n", strlen(p[0]));//err
            printf("%d\n", strlen(&p));//随机值  编译器会随机给他分配地址
            printf("%d\n", strlen(&p + 1));//随机值  &p+1  与  &p  没有差异,没啥关系
            printf("%d\n", strlen(&p[0] + 1));//5
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    int a[3][4] = { 0 };
        
            printf("%d\n", sizeof(a));//3*4*4 = 48
            printf("%d\n", sizeof(a[0][0]));//4  零行零列的元素
        
            printf("%d\n", sizeof(a[0]));//a[0]是第一行这个一维数组的数组名
            //数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节
        
            printf("%d\n", sizeof(a[0] + 1));//?
            //a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&
            //a[0]表示数组首元素的地址,也就是a[0][0]的地址
            //所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节
            
            printf("%d\n", sizeof(*(a[0] + 1)));//4
            //计算的是就是第一行第2个元素的大小
        
            printf("%d\n", sizeof(a + 1));//4 / 8
            //a是数组首元素的地址,是第一行的地址 int(*)[4]
            //a+1 就是第二行的地址
        
            printf("%d\n", sizeof(*(a + 1)));//16
            //*(a+1) --> a[1] -> sizeof(*(a+1))->sizeof(a[1]) 计算的是第二行的大小
            //a+1 --> 是第二行的地址,int(*)[4]
            //*(a+1) 访问的第二行的数组
        
            printf("%d\n", sizeof(&a[0] + 1));//4/8
            //&a[0]是第一行的地址 int(*)[4]
            //&a[0]+1 是第二行的地址 int(*)[4]
        
            printf("%d\n", sizeof(*(&a[0] + 1)));//16 计算的是第二行的大小
        
            printf("%d\n", sizeof(*a));//计算的是第一行的大小-16
            //a是数组首元素的地址,就是第一行的地址
            //*a 就是第一行
            //*a --> *(a+0) --> a[0]
        
            printf("%d\n", sizeof(a[3]));//16
            //a[3]--> int [4]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    5.1.2 例题:

    例一.
    例二.
    例三.
    例四.
  • 相关阅读:
    一键生成 API 文档的妙招
    如何使用 ELEMENTOR
    《进化优化》第3章 遗传算法
    TypeScript简介
    JavaSE_day04【数组】
    如何将本地jar包安装到maven仓库
    AI语音系统电销机器人系统搭建|AI智能|电话机器人源码|《各版本机器人部署》
    微服务实战之领域事件
    【spring cloud】(四)服务网关——gateway
    Linux Docker 安装 Redis
  • 原文地址:https://blog.csdn.net/Ghr_C99/article/details/132839689