【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)

【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)

码农世界 2024-06-05 前端 104 次浏览 0个评论

🌈个人主页:是店小二呀

🌈C语言笔记专栏:C语言笔记

🌈C++笔记专栏: C++笔记

🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅

文章目录

  • 一、数组名
    • 1.1 指针访问数组
      • 1.2 一维数组传参
      • 二、二级指针
        • 2.1 对于二级指针的运算
        • 三、指针数组
          • 3.1 指针数组模拟二维数组

            一、数组名

            在数组篇章,我们得到一个结论:数组名是首元素的地址

            验证环节:

            #include 
            int main()
            {
                int nums[]={1,2,3};
                printf("&nums[0] = %p\n", &nums[0]);
            	printf("nums = %p\n", nums);
                return 0;
            }
            结果:
            &nums[0] = 00D6F724
             nums[0] = 00D6F724  
            

            问题】:既然数组名是首元素的地址,那么为什么下面输出却不是预想的结果呢?

            int main()
            {
                int nums[10]={1,2,3};
                printf("%d\n",sizeof(nums));
                return 0;
            }
            输出结果:40。数组名是数组首元素的地址的话,那么输出的结果为什么不是4/8呢?
            

            【解释】:首先数组名是首元素的地址这结论是没错的,但是凡是都有特例

            • sizeof(array_name):sizeof单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小
            • & array_name:这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的,虽然一开始指向的地址是相同的)
              #include 
              int main()
              {
              int nums[10] = { 1,2,3,4,5,6,7,8,9,10 };
              printf("&nums[0] = %p\n", &nums[0]);
              printf("&nums[0]+1 = %p\n", &nums[0]+1);
              printf("nums = %p\n", nums);
              printf("nums+1 = %p\n", nums+1);
              printf("&nums = %p\n", &nums);
              printf("&nums+1 = %p\n", &nums+1);
              return 0;
              }
              

              通过结果得到的结果:

              1. &nums[0]和(nums)与&nums[0]+1 和(nums)+1相差了四个字节
              2. &nums和&nums+1相差40个字节

              理由】:根据上面的结论

              1. &nums[0]和(nums)都是代表首元素的地址,对此+1只跳过一个元素(数组元素)

              2. &nums都是代表整个数组的地址,对此+1只跳过一个元素(整个数组)

              1.1 指针访问数组

              int nums[]={1,2,3};
              int *p=nums;
              printf("%d",*(p+1));//p[1]=nums[1]=*(nums+1)
              

              【说明】:

              本质上nums[i]等价于*(nums+i),在编译器处理时,数组通过下标访问是转换成首元素的地址+偏移量求出元素的地址,再解引用来访问的。

              1.2 一维数组传参

              问题:将外部函数中数组在调用函数时传参,并在内部函数求数组元素个数是否可行?

              void test(int nums[])
              {
                  int sz=sizeof(nums)/sizeof(nums[0]);;
                  printf("%d",sz);//结果为1
              }
              int main()
              {
                  int nums[]={1,2,3,4,5};
                  test(nums);
                  return 0;
              }
              

              【结果】:在函数内部没有求出正确的数组元素个数。

              【理由】:因为数组名是数组首元素的地址,那么在数组传参的时候,传过去的不是一整个数组,而是数组名,也是说数组传参的本质是传递数组首元素的地址,地址的大小4/8

              【结论】:

              • 在求数组元素个数的操作在调用函数前完成
              • 一维数组传参,形参部分可以写成数组的形式(本质是指针),也是可以写成指针的形式
                数组形式:void test(int nums[])
                指针形式: void test(int *nums)
                

                二、二级指针

                问题:指针变量是存放变量的地址,是变量就是有自身的地址,那么指针变量的地址存放在哪里呢?

                int *类型存放int 类型地址
                int **类型存放int *类型地址 
                    依次类推
                

                二级指针:用于存放一级指针的地址,以此类推,N级存放N-1级的地址,但是太高级也是不常用或者直接不用三级以上的

                【分析】:

                2.1 对于二级指针的运算

                *pa是通过pa中的地址解引用,找到的是a( * pa通过a的地址找到a)

                int a=10;
                *pa = &a;//等价pa = &a
                

                **ppa是先通过 *ppa找到pa,然后对pa进行解引用找到a:( *pa,找到a)

                ** ppa = 10;
                //等价* pa = 10;
                //等价a = 10
                

                三、指针数组

                问题】:指针数组是指针还是数组

                整型数组:存放整形的数组
                字符数组:存放字符的数组
                .....
                指针数组:存放指针的数组(每个元素的都是存放地址)(而指针又指向一块空间)
                ```cpp
                int a, b, c=0;
                int* arr[5] = {&a, &b, &c};
                这里arr先跟[]结合形成数组,意味是指针数组,存放一级指针的数组
                

                顺序问题:先对外层解引用,在到内部解引用

                3.1 指针数组模拟二维数组

                int main()
                {
                	int arr1[] = {1,2,3,4,5};
                	int arr2[] = {2,3,4,5,6};
                	int arr3[] = {3,4,5,6,7};	
                    //[]优先级高于* p先是个数组,所以是数组指针
                    //P里面的元素都是地址(指针)
                	int* parr[] = { arr1,arr2,arr3};
                	for (int i = 0; i < 3; i++)
                	{
                		for (int j = 0; j < 3; j++)
                		{
                			printf("%d ", parr[i][j]);
                		}
                		printf("\n");
                	}
                	return 0;
                }
                

                【说明】:parr[i]是访问parr数组的元素{arr1,arr2,arr3},而这些是指针(地址),同时指向一片空间,需要再次解引用找到某指针的某个元素。对于上面parr[i]找到的数组元素指向了整形一维数组,p[i] [j]就是整形一维数组中元素

                注意:属于模拟二维数组的效果,二维数组也是连续存放数据的,而这里每一行不是连续存放,不是真正的二维数组


                谢谢大家的观看,这里是个人笔记,希望对你学习C有帮助。

                如果对指针篇感兴趣可以,点击该链接了解多方面学习指针开篇

转载请注明来自码农世界,本文标题:《【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,104人围观)参与讨论

还没有评论,来说两句吧...

Top