详解C语言指针与数组的关系

一、指针与一维数组

          我们常说的指针就是指针变量的意思,注意他也是变量,指针与普通的变量有区别也有联系

普通的变量相当于一个容器,容器里面存储了数值,用到了这个变量就相当于直接取走了这个数值

而指针存储的是内存地址,什么是内存地址呢?假设定义一个普通变量a,定义完成之后,系统会

在内存中给这个变量分配一片存储空间,这个存储空间的名字就叫做a,这个存储空间里面放的就

是数据,为了区分各个存储空间,就给这个存储空间分配一个地址,这个地址就是这个变量所在的

地方,程序运行的时候就很快能找到,地址就相当于一个编号。

        由于数组的数组名就是指针,也就是存储了数组首元素的地址,因此会有下面两种方式:

  int *p,a[10];

  p=a;
   
  p=&a[0];

由于都是指针,因此p与a可以直接相等,而从数组方面来说的话,p又指向了数组首元素,并且存

储了它的地址,我们可以得出一个结论:指针的本质就是存储地址;

         &数组名[某数] =  数组名 + 某数

         数组名[某数] =   *(数组名 + 某数)

 1.1  指针遍历数组

         可以直接通过数组下标直接遍历数组,如何通过指针遍历数组呢?我们只需要将数组首元素

的地址传给指针,就可以操作数组的元素了;

    void   test(int *p,int n){

         int i,sum=0;

        for(i=0;i<n;i++){

            sum+=*(p+i);   //这里的p+i指的是偏移首元素的地址,然后再用操作符取出来即可;    
       }

       return;
    }

        注意:(p+i)式子里面的i不能是浮点数,因为地址是按照字节来的,根据数据类型来看,int类

型只能4个字节4个字节的往前走,不可能存在小数个字节的;

1.2  为何要引出指针

        1.2.1  指针与数组的传递

函数是可以接受数组的指针作为参数的,这样可以避免将整个数组都复制到函数中去,减少了内存

和时间的开销,例如如下:

   void test(int *arr,int size)

注意:上面是指向数组的指针,并不是数组本身;

        1.2.2   数组作为函数的返回值

函数可以返回指向数组的指针,例如在函数内部动态的分配数组内存,然后返回指向该数组的指针

二、 指针与二维数组

        首先要明确一点,二位数组的结构是怎样的?简单写一个二维数组,看看元素地址的排列。

#include <stdio.h>

int main()
{
	
	int  n,i,j;

	scanf("%d",&n);

	int a[n][n];

	printf("Enter %d integres!\n",n*n);

	for(i=0;i<n;i++){
		
	  for(j=0;j<n;j++){
	  	
	  	scanf("%d",&a[i][j]);

	  	printf("%p\n",&a[i][j]);  //%p表示地址格式化操作符,

	  }
	     	
	} 
	 return 0;

}

        下面是运行的结果:这里说明一下,在内存中地址是按十六进制排列的,0-9,A-F,逢十六

进一,由于元素是int 类型的,因此会按照0->4->8的顺序走,8+4=12,也就是对应十六进制的C

12+4=16,逢十六进一,所以前面的6加一,从这里我们可以看出,二维数组是按照Z字型排列的

,通俗一点就是说按照行优先排列的,这就意味着每一行都存储在连续的内存块中,而指向下一

行的指针则指向下一个连续内存块的起始地址。         

   2.1   指针与二维数组的关系

             类比一维数组,二维数组名也是一个指向数组的指针,例如int  a[3][4],a表示是一个指向

整型数组的指针,且指向数组的第一行,存储的是是第一行的地址,存储的也是第一行首元素的地

址,我们接下来举个看个代码来验证这一结果性。

注意:看看是不是我们想的那样,运行结果如下所示:

     

 从上图我们可以看出,第一行的地址其实就是第一行首元素的地址,同理可得,其它行的地址也

是存储的该行首元素的地址。因为a是二级指针,a+1指的就是存储了第二行初始元素的地址,就

是相当于a+1是一个标识符,指针变量的名字就叫做a+1,通过操作符取值可以把里面的地址的值

取出来,即*(a+1),这个*(a+1)代表着的是第二行首元素的地址,也就是一级指针了,就跟我i们上

面讲述的一级指针与一维数组的关系一致了,如果要取值这一行元素的话,*(*(a+1)+j),其中j

表示的是偏移首元素的偏移量,0<=j<len,len表示的是该行的元素个数。

         下面总结一下,二级指针与二维数组的关系:

 1、 *(a+i)+j  =  &a[ i ] [ j ]

  2、*( *(a+i)+j)  =  a[ i ] [ j ]

特别是上式第一个,主要是取元素的地址的,在一维数组中有这样的关系,p[ i ] = *(p+i)

其中p是一级指针,同理可得*(a+i) =a[ i ],不过这里的是二级指针,也就是说a[ i ]才是一级指针,

存的是该行元素的首地址,然后就是*(a[ i ] +j) = a[ i ] [ j ];自己可以去试验一下。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值