关于数组和指针

来源:互联网 发布:91助手mac电脑版 编辑:程序博客网 时间:2024/06/05 06:55

1. 先来看几个例子,你能说出这几个表示方法的意义和不同点吗?

a. int *p[10]  //10个指向int类型的指针,数组里面的类型是int *,这个方式叫指针数组,可以转化成二级指针;
b. int (*p)[10]  //指向一个有10个int成员的数组,其实也就是一个2维数组p[][10],确定的第二维的长度是10,数组里面对象的类型是int,这种方式叫数组指针,可以转化成二维数组;
c. int (*p)(int)  //指向一个形参表为1个int类型,返回值为int的函数指针

d. int *p(int a) //这个是一个指针函数,函数返回的是一个地址,使用在在返回数组某一个元素的地址上;
e. int (*p[10])(int) //指针数组指针函数的结合:定义一个指针数组,数组中每个成员均是int (*p)(int) 的指针;

这几种表示方法经常出现在程序中,很容易使人混淆,需要注意的是:C语言经常用函数指针的方式实现面相对象的功能,在动态调用过程中,把实现不同功能的类似函数通过函数指针的形式赋值给真正调用的函数,来实现面相对象的过程。

 

2. 多维数组和指针

例如:整型二维数组a[3][4]:

  0  1  2  3
  4  5  6  7
  8  9  10  11

设数组a的首地址为1000,C语言允许把一个二维数组分解为多个一维数组来处理。因此数组a可分解为三个一维数组,即a[0],a[1],a[2]。每一个一维数组又含有四个元素。例如a[0]数组,含有a[0][0],a[0][1],a[0][2],a[0][3]四个元素。
数组及数组元素的地址表示如下:a是二维数组名,也是二维数组0行的首地址,等于1000。a[0]是第一个一维数组的数组名和首地址,因此也为1000,*(a+0)或*a是与a[0]等效的, 它表示一维数组a[0]的0号元素的首地址,也为1000,&a[0][0]是二维数组a的0行0列元素首地址,同样是1000。
因此,a,a[0],*(a+0),*a,&a[0][0]是相同的。同理,a+1是二维数组1行的首地址,等于1008。a[1]是第二个一维数组的数组名和首地址,因此也为1008。&a[1][0]是二维数组a的1行0列元素地址,也是1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的。由此可得出:a+i,a[i],*(a+i),&a[i][0]是等同的。此外,&a[i]和a[i]也是等同的。因为在二维数组中不能把&a[i]理解为元素a[i]的地址,不存在元素a[i]。C语言规定,它是一种地址计算方法,表示数组a第i行首地址。由此,我们得出:a[i],&a[i],*(a+i)和a+i也都是等同的。另外,a[0]也可以看成是a[0]+0是一维数组a[0]的0号元素的首地址,而a[0]+1则是a[0]的1号元素首地址,由此可得出a[i]+j则是一维数组a[i]的j号元素首地址,它等于&a[i][j]。由a [i]=*(a+i)得a[i]+j=*(a+i)+j,由于*(a+i)+j是二维数组a的i行j列元素的首地址。该元素的值等于*(*(a+i)+ j)。

试一下以下程序段

#define PF "%d,%d,%d,%d,%d,\n"
int main(void)

{
    static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
    printf(PF,a,*a,a[0],&a[0],&a[0][0]);
    printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);
    printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);
    printf("%d,%d\n",a[1]+1,*(a+1)+1);
    printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));

    return 0;
}

运行结果如下:(注意,是打印的10进制数)


其中数组地址信息如下:


说明:0x003a7038的十进制为3829816

3. 二级指针做参数

通过下面的例子来了解二级指针做函数参数时,主函数对此函数是怎么调用的。

#include "stdio.h"

typedef struct tst
{
 int x;
}tst_t;

typedef struct student
{
     int a;
     tst_t *s;
     int c;
}stu_t;

void fun(stu_t **p)
{
     int i = 0;
     for (i = 0; i < 4; i++)
     {
         if ((*(p + i))==NULL)
         {
             printf("yes\n");
         }
         else
         {
             printf("no!\n");
             if (((*(p + i))->s->x) != 0) 
             {
                  printf("no zero\n");
             }
             else
             {
                  printf("zero\n");
             }
         }
     }
}
int _tmain(int argc, _TCHAR* argv[])
{
     stu_t *tmp[4];
     stu_t t;
     tst_t p[4];
     p[0].x = 1;
     p[1].x = 0;
     p[2].x = 0;
     p[3].x = 0;
     tmp[0] = &t;
     tmp[0]->s = p;
     tmp[1] = NULL;
     //tmp[1]->s = &p[1];由于tmp[1]指向了null,调用tmp[1]的指针成员时候发生中断异常。
     tmp[2] = &t;
     tmp[2]->s = &p[2];
     tmp[3] = NULL;
     //tmp[3]->s = &p[3];由于tmp[3]指向了null,调用tmp[3]的指针成员时候发生中断异常。
     fun(tmp);
     return 0;
}

0 0
原创粉丝点击