Chinaunix首页 | 论坛 | 博客
  • 博客访问: 71841
  • 博文数量: 10
  • 博客积分: 1431
  • 博客等级: 上尉
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-15 19:45
文章分类
文章存档

2011年(1)

2010年(6)

2009年(3)

我的朋友

分类: C/C++

2010-03-16 21:17:51

二级指针和二维数组

author: fengxz

先看下面一个简单例子:

int main()

{

char *onedp = NULL;  //one dimension array

char **twodp = NULL;  //two dimension array

        char a[3][16] = {"China_and_me", "c++", "It is a desk"};

        int i = 0;

 

        twodp = (char **)a;

        for(i = 0; i < 3; i++)

{

                printf("%s\n",a[i]);      

                printf("%s\n", *(twodp + i));          

        }

        return 0;      

}

在以上程序中,twodp 是一个二级指针,a[3][16]是一个二维数组。

for本要循环输出a[3][16]中的每一个字符串,但是遗憾的是,在执行printf("%s\n", *(twodp + i))时程序就down了。

下面看一下其中用到了那些知识:

     1) 以一维数组角度看待二维数组。

         对于a[3][16],这样来认识:首先把a作为一维数组看待,不过这个数组的元素仍是数组,即有3个数组为a的元素:a[0],a[1],a[2]。因此,a+1就是跨越一个行,所以a也称为行地址。关于行指针后面叙述。

         而a[i](i=0,1,2)又是一个一维数组,他的元素为a[i][j](j=0,1,2,...15),所以a[i]+1跨越a[3][16]的一个元素大小。

2 应该要知道一点,指针变量中存放的是某个地址的值。

所以一维指针和二维指针变量的值,即onedptwodp值都是某个地址,一维指针和二维指针变量不同的是,对二维指针变量操作:*twodp仍然是一个地址,而*onedp就是代表one所指的变量了。

这样看来,对上面的程序,twodp = (char **)a;这样twodp就指向二维数组的首地址,而这个首地址指向了字符C,当i0时,twodp + i存放的是字符C的地址,那么*(twodp + i)的值就是字符C了,而字符CASCII码的16进制值是0x63,所以*(twodp + i)0x63。注意,不要忘了twodp是一个二维指针,所以*(twodp + i)仍是一个地址,不幸,该值0x63却是内存中我们所无法访问的空间。这样我们就不难理解上面程序down的原因了。知道了原因,就离解决方法不远了,不过在说解决方法之前,我们先看另一个问题

3)对指针的运算,均是以指针所代表的类型为单位进行。

如果i=2twodp = 0x0012fe90那么twodp + i是多少?

如果你答0x0012fe92,那就错了。

因为对指针的运算,均是以指针所代表的类型为单位进行。对于二级指针twodp,它的一级指针*twodp仍是指针类型,无论是char指针,还是其他指针,只要是指针类型,就占有4个字节(32位机)。所以twodp + i就是0x0012fe90 + i*4,当i=1时为0x0012fe94

4)“行指针”概念

看一个例子:

int (*p)[16];

它定义了这样一个指针:这个指针指向一个一维数组,这个一维数组共有16个元素。

如果这样使用:

int a1[16];

p = a1;

那么p+1将发生越界,因为对p而言,它以行为单位进行。它每次走一行,一行是它的最小单位。对于a1[16],一行就是16个元素。每个元素4个字节,所以每一次p+1将跨越64个字节。行指针用在二维数组表现的很充分。因为二维数组可以看成一维数组的数组。对于二维数组a[3][16],共有3行。每一行又是含有16个元素的一维数组。从刚才上面对二位数组分析,二位数组名就是该数组第0行首地址,就是行地址。但是一定要注意a不是行指针,只是一个常量。

注意定义行指针时保持和二维数组的第二维一致!因为行指针移动按照这个“维”进行的。

 

有了以上知识,我们就可以方便操作二维数组了。

对于开始的例子,为了输出二维数组a[3][16]的每个字符串,以下几种方法:

1)设一个行指针。

char (*linep)[16];  // line type pointer

 

linep = a[0];

        for(i = 0; i < 3; i++)

        {

                printf("%s\n",linep + i);      

                               

    }

 

2直接使用二级指针,不过一定注意二级指针的计算

twodp = (char **)a;

 

       

 

        for(i = 0; i < 3; i++)

        {

                printf("%s\n", twodp + i*4);           

    }      

这里一定要知道为什么是i4相乘!

如果定义二维数组bb[3][17],内容和二维数组a相同。那么将很难找到直接使用二级指针来访问b的每一个字符串的方法了。

阅读(2403) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~