• C++之函数指针、指针函数以及相关问题


    目录

    1.指针

    2.指针变量

    3.指针分类

    4.指针相关题

    5.关于判定本质是否为指针的右左法则

    6.函数指针

    1.函数名代表函数的入口地址(一个函数)

    2.函数名代表函数的入口地址(多个函数)

    3.函数指针函数

    7.扩展--函数转移表

    8.面试题1:1+2+...+n,不用if,循环,公式,不能直接输出结果

    9.面试题2:n个1~10的数据,计算1~10出现的次数


    1.指针

    指针就是一个地址

    指针也就是内存地址,指针变量是用来存放内存地址的变量,在同一CPU构架下,不同类型的指针变量所占用的存储单元长度是相同的(一般为4字节),而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。

    2.指针变量

    基类型 * 指针变量名

    指针变量是指存放地址的变量。因指针变量是一种特殊的变量,它不同于一般的变量,一般变量存放的是数据本身,而指针变量存放的是数据的地址。

    eg:

    1. int a = 68;
    2. long *p=NULL;
    3. p=&a;

    分析:

    系统为变量a分配的首地址为0X065FDF4H

    声明空指针long *p = NULL,

    p=&a是存放变量a地址的指针变量,

    即p=&a中存放的值为0x065FDF4H(a的值为68,&a的值为0x065FDF4H)。

    对变量a的访问有两种方式:

    1.直接按地址0x065FDF4H找到a的存储单元,从而对变量a进行访问;

    2.按系统为p=&a分配的地址先找到p=&a,然后根据p,&a的值(即变量a地0x065FDF4H)找到变量a在内存中的存储单元,从而对变量a进行访问。

    总结:

    对于前一种访问方式称为直接访问方式,后一种访问方式称为间接访问方式。

    如果一个指针变量存放的是某个对象的地址,则称这个指针变量指向该对象。在C++程序设计中,指针变量只有确定了指向才有意义。

    3.指针分类

    单指针 双指针  指针数组  数组指针  指针函数  函数指针 
    单指针--变量  一维数组  二维数组 函数
    双指针--变量  指针数组
    字符指针

    4.指针相关题

    1. void main()
    2. {
    3. char a[] = "123";
    4. char b[] = "123";
    5. const char c[] = "123";
    6. const char d[] = "123";
    7. const char* p1 = "123";
    8. const char* p2 = "123";
    9. const char* const p3 = "123";
    10. const char* const p4 = "123";
    11. if (a == b)
    12. cout << "a==b" << endl;
    13. if (a == c)
    14. cout << "a==c" << endl;
    15. if (c == d)
    16. cout << "c==d" << endl;
    17. if (p1 == p2)
    18. cout << "p1==p2" << endl;
    19. if (p3 == p4)
    20. cout << "p3==p4" << endl;
    21. if (p1 == p3)
    22. cout << "p1==p3" << endl;
    23. }

    a、b、c、d都在表的是数组首元素的首地址,因其地址不同,所以前三个不输出

    p1、p2、p3、p4代表的都是指向内容为"123" 的字符串(统一字符串只有一个,多个浪费空间),所以他们存储的是字符串"123"的首地址(1的地址)//不能修改

    5.关于判定本质是否为指针的右左法则

    规则:

    首先,我们找到*符号,找到变量:

    例如:

    int (*p)[4];

    1.()的优先级大,所以首先是一个指针,

    2.然后以(*p)为中心,先从右边开始看,[4]为数字,即在指针前加一个修饰词数组,即就是数组指针,

    3.再以判断过的部分(*p)[4]为中心从左边看是 int,即代表整型数组。

    综上:整型数组指针--指向数组的指针

    int *q[4] ;

    1.q[4],代表一个数组,以q[4]使用右左原则

    2.*q[4],在数组前加上修饰词指针,即就是指针数组

    3.int代表整形
     综上:整型指针数组--存储指针的数组
     

     int(*p1[5]);

    1.首先找到变量p1,p1[5]代表一个数组

    2.再以p1[5]为中心进行右左原则,得到*p1[5],即就是指针数组

    3.int代表整形

    综上:同第二类,因为()并没有真正印象到优先级 整型指针数组--存储指针的数组

    int* (*p2[5])(int);

    1.首先找到变量p2,p2[5]代表一个数组

    2.再以p2[5]为中心进行右左原则,得到*p2[5],即就是指针数组

    3.再以(*p2[5])为中心进行右左原则,得到(*p2[5])(int)即就是返回类型为整型的函数指针数组

    4.再以(*p2[5])(int)为中心进行右左原则,得到int* (*p2[5])(int),加上返回类型尾指针的函数
    综上: int*(返回值是指针的函数)(*p2[5])(int)(函数)--  指针函数指针数组

     int*p3(int n);

    1.首先找到变量p3,p3(int n)代表一个函数

    2.再以p3(int n)为中心进行右左原则,得到*p3(int n),即就是指针函数

    3.再以*p3(int n)为中心进行右左原则,得到int* *p3(int n)即就是

    指针函数--返回值为指针的函数

     int (*p4)(int,int)

    1.首先找到变量p4,(*p4)代表一个指针

    2.再以(*p4)为中心进行右左原则,得到*p4(int int),即就是函数指针

    --函数指针--指向函数的指针

    总结:

    先找出变量,以变量为中心进行右左原则开始分析,每分析完一个成分,将修饰词加在前面,再将已分析完的部分加入中心部分,依次分析直至结束

    6.函数指针

    函数指针
    * 函数名--代表函数的入口地址
    * 1.指针指向函数,由指针调用函数
    * 2.函数指针作为另外一个函数的参数
    * 3.数指针作为另外一个函数的返回值

    1.函数名代表函数的入口地址(一个函数)

    1. int Sum(int a, int b)
    2. {
    3. return a + b;
    4. }
    5. void main()
    6. {
    7. int(*p)(int, int);
    8. p = Sum;
    9. cout << Sum(4, 7) << endl;
    10. cout << p(3, 6) << endl;
    11. }

        int(*p)(int, int);//返回值为int的,里面有两个int型参数的 函数指针
        p = Sum;//函数名代表函数的入口地址
        cout << Sum(4, 7) << endl;
        cout << p(3, 6) << endl;//p指向Sum函数,两句意思一样

    2.函数名代表函数的入口地址(多个函数)

    1. int Sum(int a, int b)
    2. {
    3. return a + b;
    4. }
    5. int Max(int a, int b)
    6. {
    7. return a > b ? a : b;
    8. }
    9. int Min(int a, int b)
    10. {
    11. return a < b ? a : b;
    12. }
    13. void test(int x, int y, int(*p)(int, int))
    14. {
    15. cout << p(x, y) << endl;
    16. }
    17. void main()
    18. {
    19. int(*p)(int, int);
    20. p = Sum;
    21. test(2, 9, Max);
    22. }

        int(*p)(int, int);//返回值为int的,里面有两个int型参数的 函数指针
        p = Sum;//函数名代表函数的入口地址

    3.函数指针函数

    函数指针函数 fn是个函数名,函数里面有int n的一个参数,fn函数的返回值是一个指针,这个指针指向一类函数 int xx(int,int)

    1. int Min(int a, int b)
    2. {
    3. return a < b ? a : b;
    4. }
    5. int(*fn(int n))(int, int)//函数指针函数
    6. {
    7. cout << "fn n=" << n << endl;
    8. return Min;
    9. }
    10. void main()
    11. {
    12. cout << "函数指针作为函数返回值" << endl;
    13. cout<<fn(100)(3, 20)<
    14. int(*p)(int, int);
    15. p = fn(100);
    16. cout << p(3, 20) << endl;
    17. }

    int(*fn(int n))(int, int)//函数指针函数
    cout<     p = fn(100);//加上下一句等同于cout<     cout << p(3, 20) << endl;//与上一句一起

     

    7.扩展--函数转移表

    1. int Sum(int a, int b)
    2. {
    3. return a + b;
    4. }
    5. int Max(int a, int b)
    6. {
    7. return a > b ? a : b;
    8. }
    9. int Min(int a, int b)
    10. {
    11. return a < b ? a : b;
    12. }
    13. int Sub(int a, int b)
    14. {
    15. return a - b;
    16. }
    17. int Mul(int a, int b)
    18. {
    19. return a * b;
    20. }
    21. int Div(int a, int b)
    22. {
    23. if (b != 0)
    24. return a / b;
    25. }
    26. int Mod(int a, int b)
    27. {
    28. return a % b;
    29. }
    30. void main()
    31. {
    32. int(*p[])(int, int) = { Sum,Max,Min,Sub,Mul ,Div,Mod };
    33. int x = 20, y = 8;
    34. int n = sizeof(p) / sizeof(p[0]);
    35. for (int i = 0; i < n; i++)
    36. {
    37. cout << p[i](x, y) << endl;
    38. }
    39. }

    int(*p[])(int, int) = { Sum,Max,Min,Sub,Mul ,Div,Mod };//  函数指针数组

    运算结果会将数组中的所有函数的值都依次计算出结果

    8.面试题1:1+2+...+n,不用if,循环,公式,不能直接输出结果

    1. int f0(int n)
    2. {
    3. return 0;
    4. }
    5. int f1(int n)
    6. {
    7. static int (*pf[2])(int) = { f0,f1 };
    8. return pf[!!n](n - 1) + n;
    9. }
    10. void main()
    11. {
    12. cout << f1(100) << endl;
    13. }

    1.进入f1函数,返回pf( 非非100),即就是pf1(99)+100

    2.再进入f1函数,返回pf( 非非99),即就是pf1(98)+99

    .

    .

    .

    n.再进入f1函数,返回pf( 非非1),即就是pf(0)+1

    n+1.再进入f0函数,返回0

    类似于递归函数,依次减一,0为出口

    9.面试题2:n个1~10的数据,计算1~10出现的次数

    1. void main()
    2. {
    3. int num[] = {10,1,4,7,4,7,9,5,2,3,4,6,10,5,8,10 };
    4. int n = sizeof(num) / sizeof(num[0]);
    5. int count[11] = { 0 };
    6. int i;
    7. for (i = 0; i < n; i++)
    8. {
    9. count[num[i]]++;
    10. }
    11. for (i = 1; i <= 10; i++)
    12. cout << i << ":" << count[i] << endl;
    13. }

            count[num[i]]++;等于下面两句
            /*if (num[i] == 1)
                count[1]++;*/

    类似于桶排序,将所有数据放入0-10,这11个桶中,每次存放一个数据,该桶的计数器+1

  • 相关阅读:
    BZOJ 4612([Wf2016]Forever Young) 题解
    阿里云/腾讯云国际站账号:私服游戏服务器:阿里云CTO周靖人:AI时代,为什么阿里云一定要做开源
    含文档+PPT+源码等]精品基于PHP实现的好物优购商城|电商小程序[包运行成功]计算机毕业设计PHP毕业设计项目源码计算机PHP毕业设计微信小程序项目源码
    深入理解Spring Boot AOP:CGLIB代理与JDK动态代理的完全指南
    swiper轮播图片+视频播放,预览及页面跳转功能
    JNI相关总结
    设计模式学习(四):建造者模式
    ros 自定义订阅者Subscriber的编程实现
    Maven 插件统一修改聚合工程项目版本号
    区块链跨链技术
  • 原文地址:https://blog.csdn.net/m0_59052131/article/details/127640562