【C语言】指针进阶(1)

2024-02-27 1886阅读

温馨提示:这篇文章已超过398天没有更新,请注意相关的内容是否还可用!

 在前期的文章中,我们已经学习完了指针初阶的内容,这期我们开始学习指针的进阶部分。

指针初阶文章入口: 指针初阶

目录

重点知识概览

前期回顾

字符指针

指针数组

数组指针

数组指针的定义

&数组名VS数组名

数组指针的使用

数组参数和指针参数

一维数组传参

二维数组传参

一级指针传参

二级指针传参


重点知识概览

指针进阶部分的全部重点内容:

  • 1. 字符指针
  • 2. 数组指针
  • 3. 指针数组
  • 4. 数组传参和指针传参
  • 5. 函数指针
  • 6. 函数指针数组
  • 7. 指向函数指针数组的指针
  • 8. 回调函数
  • 9. 指针和数组面试题的

    这些内容我们大概会有3~4篇文章来完成,欢迎大家的点赞与收藏。

    前期回顾

    指针的由来:

    在计算机内存中会划分一个个的内存单元,每个内存单元都有一个独立的编号,这些编号也被称为地址,地址在C语言中被称为指针。指针(地址)需要存储到变量中,这个变量就被称为指针变量。

    【C语言】指针进阶(1) 我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念:

    1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。

    2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。

    3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。

    4. 指针的运算。

    这个章节,我们继续探讨指针的高级主题。

    字符指针

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

    一般使用:

    【C语言】指针进阶(1)

    【C语言】指针进阶(1)

    代码    const  char* p = " abcdef " ; 特别容易让同学以为是把字符串 abcdef 放到字符指针 p 里了,但是本质是把字符串 abcdef 首字符的地址放到了p中。

    【C语言】指针进阶(1)

     上面代码的意思是把一个常量字符串的首字符 a 的地址存放到指针变量 p 中。

    下面有一道笔试题:

    #include 
    int main()
    {
    	char str1[] = "hello world.";
    	char str2[] = "hello world.";
    	const char* str3 = "hello world.";
    	const char* str4 = "hello world.";
    	if (str1 == str2)
    		printf("str1 and str2 are same\n");
    	else
    		printf("str1 and str2 are not same\n");
    	if (str3 == str4)
    		printf("str3 and str4 are same\n");
    	else
    		printf("str3 and str4 are not same\n");
    	return 0;
    }
    

    这里最终输出的是:

    【C语言】指针进阶(1)

     原因:【C语言】指针进阶(1)

     这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会 开辟出不同的内存块。所以str1和str2不同,str3和str4相同。

    指针数组

    在《指针》章节我们也学了指针数组,指针数组是一个存放指针的数组。 这里我们再复习一下,下面指针数组是什么意思?

    可以使用类比的方法来记忆:

    • 整形数组——存放整形的数组
    • 字符数组——存放字符的数组
    • 指针数组——存放指针的数组

      【C语言】指针进阶(1)

       使用指针数组模拟实现二维数组:

      int main()
      {
      	int arr1[] = { 1,2,3,4,5 };
      	int arr2[] = { 2,3,4,5,6 };
      	int arr3[] = { 3,4,5,6,7 };
      	int* arr[] = { arr1,arr2,arr3 };
      	int i = 0, j = 0;
      	for (i = 0; i  
      

      【C语言】指针进阶(1)

        打印结果:

      【C语言】指针进阶(1)

      数组指针

      数组指针的定义

      数组指针是指针?还是数组? 答案是:指针。

      我们已经熟悉:

      • 整形指针——指向整形变量的指针,存放整形变量地址的指针变量。
      • 字符指针——指向字符变量的指针,存放字符变量地址的指针变量。
      • 数组指针——指向数组的指针,存放的是数组的地址。

        下面代码哪个是数组指针?

        【C语言】指针进阶(1)

         int (*p)[10]是数组指针。

        【C语言】指针进阶(1)

        &数组名VS数组名

        数组名的理解:

        数组名是数组首元素的地址:

        【C语言】指针进阶(1)

          虽然数组名是数组首元素的地址,但是存在两个例外:

        1.sizeof(数组)名,这里的数组名不是数组首元素的地址,这里的数组名表示的是整个数组,             sizeof(数组)名计算的是整个数组的大小,单位是字节。

        2.&数组名,这里的数组依然表示整个数组,&数组名取出的是整个数组的地址。

           除此之外,其他地方所有的数组名都是数组首元素的地址。

        为了能让大家看出上面代码中arr,&arr[0],&arr的区别,我们可以使用下面的方法:

        1.在VS编译器中进行调试时,使用监视窗口观察类型:

        【C语言】指针进阶(1)

          2.不同类型指针加1移动的步长会有所不同:

        【C语言】指针进阶(1)

         对于数组名来说,&数组名得到的是整个数组的地址

        【C语言】指针进阶(1)

        【C语言】指针进阶(1)

        数组指针的使用

         那数组指针是怎么使用的呢? 既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。 看代码:

        int main()
        {
        	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
        	int(*p)[10] = &arr;  //*&arr==arr
        	int i = 0;
        	for (i = 0; i  
        

        我们在实际应用中,很少会使用这种方式来写代码。那么数组指针怎么试着用呢?一般在二维数组上才方便。

        我们平时调用函数使用二维数组进行传参时,一般使用形参是指针的形式:

        //常规方法——二维数组传参,形参是二维数组
        void Print(int arr[3][5], int r, int c)
        {
        	int i = 0, j = 0;
        	for (i = 0; i  
        

        而今天,我们可以使用指针的形式进行传参:

        【C语言】指针进阶(1)

        //二维数组传参——形参是指针的形式
        void Print2(int(*p)[5], int r, int c)
        {
        	int i = 0, j = 0;
        	for (i = 0; i  
        

        总结:一维数组传参,形参部分可以是数组,也可以是指针。

        //形参是数组的形式
        void test1(int arr[],int sz)
        {}
        //形参是指针的形式
        void test2(int *p,int sz)
        {}
        int main()
        {
        	int arr[5] = { 0 };
        	test1(arr, 5);
        	test2(arr, 5);
        	return 0;
        }

        二维数组传参,形参部分可以是数组,也可以是指针

        //形参是数组
        void test3(char arr[3][5],int r,int c)
        {}
        //形参是指针
        void test4(char(*p)[5], int r, int c)
        {}
        int main()
        {
        	char arr[3][5] = { 0 };
        	test3(arr, 3, 5);
        	test4(arr, 3, 5);
        	return 0;
        }

         

        数组参数和指针参数

        在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?

        一维数组传参

        判断下列函数设计的是否正确:

        #include 
        void test(int arr[])//ok?
        {}
        void test(int arr[10])//ok?
        {}
        void test(int* arr)//ok?
        {}
        void test2(int* arr[20])//ok?
        {}
        void test2(int** arr)//ok?
        {}
        int main()
        {
        	int arr[10] = { 0 };
        	int* arr2[20] = { 0 };
        	test(arr);
        	test2(arr2);
        }

        【C语言】指针进阶(1) 

        二维数组传参

        判断下列函数设计的是否正确:

        void test(int arr[3][5])//ok?
        {}
        void test(int arr[][])//ok?
        {}
        void test(int arr[][5])//ok?
        {}
        void test(int* arr)//ok?
        {}
        void test(int* arr[5])//ok?
        {}
        void test(int(*arr)[5])//ok?
        {}
        void test(int** arr)//ok?
        {}
        int main()
        {
        	int arr[3][5] = { 0 };
        	test(arr);
        }
        

        【C语言】指针进阶(1)

        总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。

        因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。这样才方便运算。

        一级指针传参

        【C语言】指针进阶(1)

         思考: 当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

        【C语言】指针进阶(1)

        二级指针传参

        【C语言】指针进阶(1)

         打印结果:【C语言】指针进阶(1)

         思考: 当函数的参数为二级指针的时候,可以接收什么参数?

        【C语言】指针进阶(1)

         

        今天的文章就先讲到这里,本章剩下的内容还会继续更新~~

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]