码迷,mamicode.com
首页 > 编程语言 > 详细

数组 指针杂记

时间:2015-09-04 21:09:07      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:

  1. 一维数组

    一维数组例如:int a[5]={0};

    数组实际上是一种构造类型,是内存的一段连续的存储区域。

    其中int指明了内存访问方式,包括元素的类型,每次跳跃的步长;

    其中5指明了构造类型中数据元素的个数,也就是说指明了数组访问时候的可偏移的范围;

    其中a有两重含义:

    1).作为数组名,a表示一种构造数据类型,这也就是为什么 sizeof(name) == sizeof(type [N])。

    2).作为数组名,访问成员时它是首元素的地址 name[i] == *(name+i) == i[name]。

    其中{0},表示部分初始化,这样写代表把第一个元素初始化为0,当我们部分初始化时候,没有被我们初始化的元素自动初始化为0,而不是说我们{0}就把全部的元素初始化为0,若是{10},也就是第一个元素10,其他元素自动为0.

    对于数组可做如下理解:

    类型:type [N]

    定义:type name[N]

    大小:sizeof(type [N]) 或 sizeof(name)

    但是当我们 做这样的定义:int *p=name;或者把数组作为参数传递到函数中时,这个时候再求sizeof(p)的大小就仅仅是当前系统下一个指针类型的大小了(32位系统指针类型大小为4个字节,64为系统指针类型为8个字节)。若是在数组定义的区域内对数组名求sizeof()的到的就是整个数组在内存中所占空间大小。

    为什么非要是a[0]开始呢?[ ]可以理解为基址变址运算符,对于a[0]来说,a是基址,0是偏移量,合起来就是变址,a[0]等价于*(a+0),由于a代表首元素的地址,所以只有当a偏移0个单位才可以访问到首元素,所以必须是a[0]开始。基于以上原理,其实 a[i] 可以写成 i[a],它依然等价于*(a+i)。

    C语言不允许数组越界,但是自己不做越界检查,要程序员自己做越界检查,所以要是访问越界,那结果将是没有定义的,会造成不可预知的错误。

    一维数组名,本质上是一个一级指针,但是对一维数组名做 & 运算,得到的是一个数组指针,而不是一个二级指针。

    int array[10];

    int (*p)[10]=&array;//这是正确的

    int **p=&array;//这是错误的

    可以通过一级指针修改0级指针的内容,可通过N级指针修改N-1级指针的指向,总结起来还是一句话,通过指针可以修改它所指向的内容。

    下面是一下大小还有跳跃幅度的大小比较程序:

  

 1 #include <stdio.h>
 2 int main(void)
 3 {
 4     //对于一个普通的int型变量
 5     int a;
 6     printf("&a=%p\n",&a);
 7     printf("&a+1=%p\n",&a+1);
 8     int *p = NULL;
 9     printf("p = %p p +1 = %p\n",p,p+1);
10     /*
11      * &a+1比&a大4,原因是&a是一个int *类型,每次跳跃步长是4个字节,
12      * 相应的一个char类型的则每次跳跃1个字节
13     */
14     int array[10];
15     printf("array = %p\n",array);
16     printf("array +1 = %p\n",array+1);
17     /*后者比前者大4*/
18     printf("&array = %p\n",&array);
19     printf("&array+1 = %p\n",&array+1);
20     /*后者比前者大10*4=40,&array表示一个指向 10个int 的数组指针*/
21     printf("&array[0] = %p\n",&array[0]);
22     printf("&array[0] +1 = %p\n",&array[0]+1);
23     /*后者比前者大4*/
24     return 0;
25 }
  1. 二维数组

    二维数组本质上也是一维数组,只是数组成员由基本数据类型变成了构造数据类型(一维数组)。

    定义形式:type name[m][n];其实等价于type[n] name[m],可以这么理解。一维数组的部分初始化和清零依然适用于二维数组。

    访问概念辨析:

    a表示第0行的首地址,a+i表示第i行的首地址。

    *(a+i)    等价于a[i]    等价于&a[i][0],表示第i行第0个元素的地址;

    *(a+i)+j    等价于a[i]+j    等价于&a[i][j],表示第i行的第j个元素的地址;

    *(*(a+i)+j)    等价于*(a[i]+j)    等价于a[i][j],表示第i行的第j个元素;

    二维数组在内存中开始连续的一维空间,所以依旧可以把二维数组当成一维数组来访问,但是需要强制转化:

 1 #include <stdio.h>
 2 int main()
 3 {
 4     int array[2][3] = {9,8,7,6,5,4};
 5     int i,j;
 6     for(i=0;i<2; i++)
 7     {
 8         for(j=0;j<3;j++)
 9         {
10             printf("%d ",array[i][j]);
11         }
12         putchar(10);
13     }
14     int *p = (int *)array;
15     for(i=0; i<6;i++)
16     {
17         printf("%d ",p[i]);
18     }
19     return 0;
20 }

相应的也可以把一维数组当二维数组来使用,但是这个也需要强制转换,如:int (*p)[2]=(int (*) [2])array;其中array是一维数组名。

如何传递一个二维数组到函数中,例如有二维数组:int a[3][4];则接收它的函数参数是 function(int (*p)[4], n);

二维数组中一些地址间的差异辨析:

 1 int main(void)
 2 {
 3     int a[3][5]={0};
 4     int *p=(int *)a;
 5     printf("%d\t,%d\n",sizeof(a),sizeof(p));//60 8
 6     printf("&a[0]=%p,&a[0]+1=%p\n",&a[0],&a[0]+1);//相差20=5*4
 7     printf("a=%p\t,a+1=%p\n",a,a+1);//相差20=5*4
 8     printf("&a=%p\t,&a+1=%p\n",&a,&a+1);//相差60=5*4*3
 9     return 0;
10 }
  1. 二级指针比较典型的是用二级指针管理二维空间

数组 指针杂记

标签:

原文地址:http://www.cnblogs.com/luojialin/p/4782318.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!