二级指针和二维数组

级指针和二维数组之间关系的理解.
我们知道char array[]=”abcdef”;   array是数组的首地址,
那么在二维数组中array当然也是数组的首地址,
看看这个定义char Array[][3] ={“ab“,“cd“,“ef“};
怎么知道的呢?定义这样一个数组,在vc调试窗口中
我们看到:
Array ---------0x64324234
  |------Array[0]---0x64324234 “ab“
  |------Array[1]---0x64324337 “cd“
  |------Array[2]---0x6432433A “ef”
已经很明白了,实际编译器是这样实现二维数组的,实际上Array是“一维指针数组“的首地址,其中每一个元素指针都
对应一个字符串,那么好我们来看看是否可以这样来使用Array二维数组.
char **pArray = Array;编译器提示出错,怎么办呢?加个(char **)试试,仍然出错,设断看一下pArray的值和Array
的值是相等的,但我们是否可以象使用Array[i]那样来同样输出字符串呢?很明显是不行的,编译器不会把
pArray+i处理成pArray+i*3寻找到第i个指针的地址,而只是简单的加了一个i.这说明编译器只做了很简单的将地址值赋给
了pArray,而它实际没有任何意义.我们不能用它来访问任何数据.很奇怪吗?
再来看看这样定义char *p[] = {“ab“, “cd“, “ef“};定义了一个指针数组.char **sp = p;这样的用法经常看到,为什么这样
就可以使用sp[i]来访问字符串了呢,的确编译器在编译的时候识别出了sp是一个指向一维数组的指针的
指针,那么我们就可以把它做为数组名来操纵整个数组了

 

 

 

先看下面一个简单例子:

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的每一个字符串的方法了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值