• C语言 ——深入理解指针(2)



    在这里插入图片描述

    1. 数组名的理解

    这里我们使用 &arr[0] 的方式拿到了数组第一个元素的地址,但是其实数组名本来就是地址,而且是数组首元素的地址,我们来做个测试。

    #include 
    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;
    }
    

    输出结果:
    在这里插入图片描述

    我们发现数组名和数组首元素的地址打印出的结果一模一样,数组名就是数组首元素(第一个元素)的地址。

    数组名如果是数组首元素的地址,那下面的代码怎么理解呢?

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

    输出的结果是:40,如果arr是数组首元素的地址,那输出应该的应该是4/8才对。

    其实数组名就是数组首元素(第一个元素)的地址是对的,但是有两个例外:

    • sizeof(数组名),sizeof中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,
      单位是字节
    • &数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素
      的地址是有区别的)

    除此之外,任何地方使用数组名,数组名都表示首元素的地址。

    2. 二级指针

    指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?

    这就是二级指针。

    在这里插入图片描述
    对于二级指针的运算有:

    • *ppa 通过对ppa中的地址进行解引用,这样找到的是pa , *ppa 其实访问的就是pa .
    int b = 20;
    *ppa = &b;//等价于pa = &b;
    
    • **ppa 先通过*ppa 找到pa ,然后对pa 进行解引用操作: *pa ,那找到的是a .
    **ppa = 30;
    //等价于*pa = 30;
    //等价于a = 30;
    

    3. 指针数组

    指针数组,是存放指针的数组。

    在这里插入图片描述

    指针数组的每个元素都是用来存放地址(指针)的。

    在这里插入图片描述
    指针数组的每个元素是地址,又可以指向一块区域。

    4. 字符指针变量

    在指针的类型中我们知道有一种指针类型为字符指针char* ;

    int main()
    {
    	char ch = 'w';
    	char *pc = &ch;
    	*pc = 'w';
    	return 0;
    }
    

    5. 数组指针变量

    数组指针变量:存放的是数组的地址,能够指向数组的指针变量。

    int (*p)[10];
    

    解释:p先和*结合,说明p是一个指针变量,然后指针指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫 数组指针

    这里要注意:[]的优先级要高于号的,所以必须加上()来保证p先和结合。

    在这里插入图片描述

    数组指针类型解析:

    int (*p) [10] = &arr;
    | | |
    | | |
    | | p指向数组的元素个数
    | p是数组指针变量名
    p指向的数组的元素类型
    

    6. 函数指针变量

    函数指针变量是用来存放函数地址的。

    #include 
    void test()
    {
    	printf("hehe\n");
    }
    int main()
    {
    	printf("test: %p\n", test);
    	printf("&test: %p\n", &test);
    	return 0;
    }
    

    输出结果如下:

    test: 005913CA
    &test: 005913CA
    

    确实打印出来了地址,所以函数是有地址的,函数名就是函数的地址,当然也可以通过&函数名的方式获得函数的地址。

    如果我们要将函数的地址存放起来,就得创建函数指针变量咯,函数指针变量的写法其实和数组指针非常类似。如下:

    void test()
    {
    	printf("hehe\n");
    }
    void (*pf1)() = &test;
    void (*pf2)() = test;
    int Add(int x, int y)
    {
    	return x + y;
    }
    int(*pf3)(int, int) = Add;
    int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的
    

    函数指针类型解析:

    int (*pf3) (int x, int y)
    | | ------------
    | | |
    | | pf3指向函数的参数类型和个数的交代
    | 函数指针变量名
    pf3指向函数的返回类型
    int (*) (int x, int y) //pf3函数指针变量的类型
    

    7. 函数指针数组

    函数指针数组是用来把函数的地址存到一个数组中

    int (*parr1[3])();
    

    parr1 先和[] 结合,说明 parr1是数组,数组的内容是什么呢?

    是int (*)() 类型的函数指针。

  • 相关阅读:
    [webservice] springboot整合cxf
    Hbase架构与存储组件结构与功能
    WZOI-227我家的门牌号
    【x265 源码分析系列】:概述
    计算机专业的学生需要每天刷题吗?
    Flutter 在 windows 上的开发环境设置
    排序算法性能王——快速排序
    pymysql的使用,sql注入问题
    为什么都说NFS读写性能差,如何进行优化?
    Java实现HTTP的上传与下载
  • 原文地址:https://blog.csdn.net/fj123789/article/details/140943049