指针浅谈(三)

     在指针浅谈(二)http://t.csdnimg.cn/SKAkD中我们讲到了const修饰指针、指针运算、野指针、assert断言和传址调用的内容,今天我们继续学习有关数组名、指针访问数组、一维数组传参的本质相关的内容,内容比较深入,如果觉得哪里讲解的不行,可以参考其他大佬的文章呦。

1.数组名的理解

     在之前我们使用指针访问数组时,有以下代码:

int arr[10]={1,2,3,4,5,6,7,8,9,10};
int* p=&arr[0];

     这里&arr[0]表示取出数组第一个元素的地址赋给指针变量p,但是你看下面这个代码和运行结果:

#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",arr);
   return 0;
}

     你会神奇的发现,wc,这出错了吧,这怎么可能,数组名的地址怎么能和数组第一个元素的地址相同呢?但事实上,数组名就是数组首元素的地址。

      这时候倘若我放出下面这段代码,阁下该如何应对?

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

       我直接懵逼了,到底哪个是对的?其实两个都是对的,数组名确实是数组首元素的地址,但在两个情况下是例外的:

 (1)sizeof(数组名):sizeof中放数组名,数组名表示整个数组,计算整个数组的大小。

 (2)&数组名,这里的数组名表示整个数组,取出的是整个数组的地址,这和首元素的地址是有区别的。区别就在于下面这段代码

#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[0]+1 = %p\n", &arr[0]+1);
 printf("arr = %p\n", arr);
 printf("arr+1 = %p\n", arr+1);
 printf("&arr = %p\n", &arr);
 printf("&arr+1 = %p\n", &arr+1);
 return 0;
}

     我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1相差4个字节,这是我们意料之中的,毕竟数组名是数组首元素的地址,但&arr和&arr+1相差40个字节,这是因为&arr是数组的地址,+1之后直接跳过整个数组,虽然它和数组首元素地址相同,但区别就在于指针+-运算跳过的多少。

     总的来说,数组名是数组首元素的地址,但是有sizeof和&数组名两个意外。

2.使用指针访问数组

     讲的是指针,那我们就要用指针,已经知道了这么多关于数组的知识,就应该学习如何用指针访问数组。

#include 
int main()
{
 int arr[10] = {0};
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 //输⼊
 int* p = arr;
 for(i=0; i

      这段代码怎么理解呢?其实并不难,将数组首元素的地址赋给了指针变量p,那我们就可以访问整个数组,毕竟数组是一段连续的存储空间,知道了首元素地址,就可以顺藤摸瓜找到其他元素,运用指针运算,遍历整个数组进行赋值,因为数组首元素也是地址,相当于一个指针,所以也可以写成arr+i,等价于arr[i]。其实数组名arr和p在这里等价,所以也可以是p[i],输出时,我们需对指针变量解引用获取元素值即可。

3.一维数组传参的本质

     我们知道数组是可以传递给函数的,那数组是把自己所有元素全部传过去吗?显然不是,在早期的计算机设备中,内存是很小的,如果一下传很多元素过去,会很占用内存,效率低下,那数组是怎么传过去呢?下面就让我们了解一下。

     之前我们都是在函数外部计算数组的元素个数,那能不能在函数内部进行求解呢?

#include 
void test(int arr[])//形参也可以写成int* arr,写成数组形式,本质上还是指针
{
 int sz2 = sizeof(arr)/sizeof(arr[0]);
 printf("sz2 = %d\n", sz2);
}
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int sz1 = sizeof(arr)/sizeof(arr[0]);
 printf("sz1 = %d\n", sz1);
 test(arr);
 return 0;
}

     我们发现其实并不能这样做,这时候就要学习数组传参的本质了,刚才学到数组名是数组首元素的地址,那传参传的是数组名,也就是说本质上数组传参传递的是数组首元素的地址。

     所以函数形参应该使用指针变量来接收首元素地址,那我们在函数内部写sizeof(arr)计算的是一个地址的大小,不是数组的大小,正是因为这样,我们在函数内部是没有办法求数组元素个数的。

     今天的指针先讲到这里,下期再见!

你可能感兴趣的:(C语言,c语言)