数组 指针杂记

来源:互联网 发布:无绳跳绳 知乎 编辑:程序博客网 时间:2024/06/05 08:19
  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级指针的指向,总结起来还是一句话,通过指针可以修改它所指向的内容。

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

  2. #include <stdio.h>int main(void){    //对于一个普通的int型变量    int a;    printf("&a=%p\n",&a);    printf("&a+1=%p\n",&a+1);    int *p = NULL;    printf("p = %p p +1 = %p\n",p,p+1);    /*     * &a+1比&a大4,原因是&a是一个int *类型,每次跳跃步长是4个字节,     * 相应的一个char类型的则每次跳跃1个字节    */    int array[10];    printf("array = %p\n",array);    printf("array +1 = %p\n",array+1);    /*后者比前者大4*/    printf("&array = %p\n",&array);    printf("&array+1 = %p\n",&array+1);    /*后者比前者大10*4=40,&array表示一个指向 10个int 的数组指针*/    printf("&array[0] = %p\n",&array[0]);    printf("&array[0] +1 = %p\n",&array[0]+1);    /*后者比前者大4*/    return 0;}

    二维数组

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

    定义形式: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个元素;

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

    #include <stdio.h>int main(){    int array[2][3] = {9,8,7,6,5,4};    int i,j;    for(i=0;i<2; i++)    {        for(j=0;j<3;j++)        {            printf("%d ",array[i][j]);        }        putchar(10);    }    int *p = (int *)array;    for(i=0; i<6;i++)    {        printf("%d ",p[i]);    }    return 0;}

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

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

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

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




0 0
原创粉丝点击