Chinaunix首页 | 论坛 | 博客
  • 博客访问: 657503
  • 博文数量: 151
  • 博客积分: 3498
  • 博客等级: 中校
  • 技术积分: 1570
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-28 18:10
文章分类

全部博文(151)

文章存档

2014年(12)

2013年(17)

2012年(17)

2011年(5)

2010年(12)

2009年(2)

2007年(26)

2006年(22)

2005年(38)

分类: LINUX

2009-08-09 14:58:46

对C的指针的使用总是让人胆战心惊啊,因为看<>讲到指针的时候,突然又有一些想法,
但是好像想不明白,于是自己又写了下面的程序实践了一下。

如果我们想动态的分配一个矩阵的长和宽,我们定义了如下的一个矩阵:
int **jj; //jj 是一个指向 int型指针 的 指针。
简单的来看 jj就是一个指针,然后这个指针所指向的内存单元 又是一个指针(p2),
然后p2这个指针了指向了int型的内存单元。

问题就在于指针,内存单元,地址这些概念不好区分,所以使用起来就有麻烦了。
还有就是内存布局的概念在理解指针上也是很重要的,
然后编译器在编译完成后分配虚拟地址也要理解。

现在回到矩阵的问题上来,既然已经分配了jj作为矩阵,那么它的行和列,我们现在其实是不知道的,
我们需要动态的申请内存。
jj作为变量,每一个变量都是分配了一个地址的,也就是jj是一个内存地址的代号。
如何知道jj的地址在哪儿里,使用
&jj
就可以看到jj的地址了,32位机器上为:0x0012ff20
我们通过一个函数来完成这个矩阵的内存申请和初始化,怎么写它的函数接口了。
我们需要另外一个地址来保存jj变量的地址,那我们定义一个指针来指向jj.
int **   *pjj=&jj;   //不能这样定义(int **) *pjj=&jj,这样变成类型conversion了。
当然中间为了容易理解,我加了空格。然后用这个pjj作为函数参数传递进去,就可以分配jj的内存了。
所以函数的声明如下:
void test(int ***a,int row)

另外,多个*号定义的东西成为多级指针,三个*成为3级指针。
然后我们这样传递参数:
test(pjj,10);
则形参a的解释如下:
&a 即为pjj变量的内存地址,*a即为指针变量jj,因为jj还没有被非配内存,
所以它所指向的内存为0xCCCCCCCC,那么& *a则为存放变量jj的内存地址。
程序的输出为:
0x0012ff20:0x0012FEB4  //实际debug 的时候0x0012ff20在内存中显示为:
jj 0x0012ff20     CC  CC   CC   CC
a  0x0012FEB4     20  FF   12   00
下面就是验证理论的代码。
cout    <<&*a
        <<":"
        <<&a
        <<":"
        <
那么我们首先来分配10行,因为每一行都是一个指针,所以如下:
*a=new int*[row]; //注意 是 int*,所以为jj申请了10个int*的的空间。
                                                   
然后我们为每一行申请10个int类型的元素个数。
*(*a+i)=new int [10];      //等号“=”的右边分配10个int的空间。
左边(*a也即是jj):
0x0012ff20                                                    
*a -->[0]-->【】【】【】【】【】【】【】【】【】【】
   -->[1]-->【】【】【】【】【】【】【】【】【】【】
   -->[2]-->【】【】【】【】【】【】【】【】【】【】
   -->[3]-->【】【】【】【】【】【】【】【】【】【】
   -->[4]-->【】【】【】【】【】【】【】【】【】【】
   -->[5]-->【】【】【】【】【】【】【】【】【】【】
   -->[6]-->【】【】【】【】【】【】【】【】【】【】
   -->[7]-->【】【】【】【】【】【】【】【】【】【】
   -->[8]-->【】【】【】【】【】【】【】【】【】【】
   -->[9]-->【】【】【】【】【】【】【】【】【】【】
怎么初始化该矩阵呢?
i表示行,j表示列,则
*(*(*a+i)+j)=atoi(tmp);//tmp为坐标值, *(*a+i)+j 表示指向的i行j列的内存单元,
要想对这个单元赋值,则需要使用*表示取内存单元的值。
==========================================================
退出矩阵内存申请和初始化函数后,
本例内存地址图:
&pjj (pjj 实际为0x0012ff20)
0x0012FF14  20 FF 12 00 24 FF 12 00

&jj(jj实际为0x00481c80)
0x0012FF20  80 1C 48 00 28 FF 12 00

jj[0]是第一行的首地址(jj[0]实际为0x00481c20)
0x00481C80  20 1C 48 00 C0 1B 48 00

jj[0][0]所在的内存单元为0x00481C20(同为jj[0]的指向的内存地址) 
00481C20  0A 00 00 00 0B 00 00 00  
00481C28  0C 00 00 00 0D 00 00 00  
00481C30  0E 00 00 00 0F 00 00 00  
00481C38  10 00 00 00 11 00 00 00  
00481C40  12 00 00 00 13 00 00 00

下面就是程序源码,注意上面的概念如果用数组下标操作,会容易理解点。
 

#include "stdafx.h"
#include <iostream>
#include "stdio.h"
#include "stdlib.h"

using namespace std;
void test(int ***a,int row)
{
    cout<<&*<<":"<<&a <<":" <<endl;

    *a=new int*[row];
    for (int i=0; i<row; i++)
    {
        *(*a+i)=new int [10];
        for(int j =0;j<row;j++)
        {
            char tmp[20];
            memset(tmp,0,sizeof(tmp));
            sprintf(tmp,"%d%d",i+1,j);         
            *(*(*a+i)+j)=atoi(tmp);
            cout << *(*(*a+i)+j) << " " ;
        }
        cout << endl;
    }  
}
void out()
{
    /*
  char *p,*pp,*pstr="test is go\n";
  int len=0; 
  p =pstr;
  while(*p++){len++;pp=p;}
  cout<   cout << pstr <<":" << p- pstr <   */

   int a=9;
   int *p,**jj,*j=0;
   int **pp;
   pp=&p;  
   p=&a;
   cout << &p << ":" <<*p <<":" << &a<<":" << &pp<<endl;
   cout << &jj <<":" <<endl;
   int ** *pjj=&jj;
   test(pjj,10);

   for (int i=0; i<10 ;i++)
   {
     for (int j =0;j<10;j++)
     {
         int *p =jj[i];
         cout <<*(p+j) << " ";
     }
     cout << endl;
   }
   return ;
}

int main(int argc, char* argv[])
{
    out();
    return 0;
}

阅读(718) | 评论(0) | 转发(0) |
0

上一篇:人生能有几个5年

下一篇:歌声响起

给主人留下些什么吧!~~