高质量程序设计指南c++/c语言(29)--深度探索指针和数组

转载:http://blog.csdn.net/shizhixin/article/details/7050592
int *a[2]; //sizeof(a):8 int (*b)[2]; //sizeof(b):4 int c[3]; //sizeof(c):12

上面3个都了解吗?轻松加愉快地看下面这张图:

    cout << typeid(new float).name() << endl;   //float *,它跟数组没有丁点关系
    cout << typeid(&new float).name() << endl;  //float **
    cout << endl;

    float f[5] = {1,2,3,4,5};
    cout << typeid(f).name() << endl;        //float *  表面上是float *,实际上是float数组,通过下面的&f可以看出来,(注意红蓝内容的区别)数组名永远不等于指针
    cout << typeid(&f).name() << endl;       //float (*)[5]
    cout << *(*(&f) + 2) << endl;            //3 *(&f)这样好无聊啊,&f是指向数组的指针,*(&f)是数组本身,即数组的首地址
    cout << endl;


    cout << typeid(new float *).name() << endl;      //float **
    cout << typeid(new float[5]).name() << endl;     //float *
    cout << typeid(new float[2][5]).name() << endl;  //float (*)[5]
    cout << typeid(&new float[2][5]).name() << endl; //float (**)[5]
    cout << endl;

    float g[2][5] = {{1,2,3,4,5}};
    cout << typeid(g).name() << endl;                 //float (*)[5] 表面上是float (*)[5],实际上是float二维数组,通过下面的&g可以看出来,(注意红蓝内容的区别)数组名永远不等于指针
    cout << typeid(&g).name() << endl;                //float (*)[2][5]

      char s2[6][6];
      s2[0] = "hello";  //error

    s2,s2[0],s[1]...的值都是不能再改变的

 上面的知识可能有点难度啦,哈哈,继续

    float (**q)[5];
    float a[2][5] = {{1,2,3,4,5}};
    q = &new float[2][5];        //ok    &new float [2][5]的类型为float (**)[5]
    q = &a;                       //error &a的类型为float(*)[2][5]

    float (*c)[5];
    c = a;              //a可以作为float(*)[5]看待
    q = &c;
    q = &(c+1);         //'&' requires l-value,注意一下,c+1的结果是一个临时对象,其地址不可取,这条语句运行完毕后,临时对象销毁。

继续

    int * pb = new int;
    int ** pa = new int *;
    int (**q)[5] = new (int (*)[5]);

       pb指针,它指向new的存储区的数据类型是int型的,同样,pa指向的是int*的数据类型,那new的话应该new int*;所以对于我们的int(**q)[5],q是指向(数组指针b)的指针,而b的类型是int (*b)[5],所以应该这么new:int (**q)[5] = new int(*)[5]);

 

到此处,掌握得应该可以啦,好吧,继续探索

    float (**q)[5];
    float a[2][5] = {{1,2,3,4,5}};

    *q = a;

     上面最后一句*q = a;正确吗?貌似是正确的,因为 a可以看做是float (*)[5]类型的,而*q也是float[5]类型的,所以赋值是没有问题的。对的,*q = a;这句编译是正确的,但是运行时就会出现错误,为什么呢,且听我慢慢道来。float (**q)[5];不管指向什么复杂的东西,q就是一个指针,假设此句是在非全局环境下(全局变量默认值为0),那么q的值是随机的,也就是没有对q初始化,是野指针。即q指针变量内存放的是一个非法地址,*q=a;的意思是要把a的值存储到这个非法地址内,这必然是错误的。归根结底就是少了一级指针的定义。

    解决方法:那就生成一个一级指针吧

(1)在栈内生成一个一级指针

    float a[2][5] = {{1,2,3,4,5}};
    float (**q)[5];
    
    float (*c)[5];
    c = a;
    q = &c;

    for(int i=0;i<5;i++)
    {
        cout<<*(**q+i)<<endl;
        printf("%p\n",**q+i);
    }

(2)在堆内生成一个一级指针

    float a[2][5] = {{1,2,3,4,5}};
    float (**q)[5] = new (float (*)[5]);
    
    *q = a;

    for(int i=0;i<5;i++)
    {
        cout<<*(**q+i)<<endl;
        printf("%p\n",**q+i);
    }

最后以一个简单的循环输出结束本文的内容:

float a[2][5]={{1,2,3,4,5},{7,8,9,0,1}};
float (*b)[5];
b=a;
for (int i=0;i<2;i++)
{
    cout<<**(b+i)<<endl;   //output: 1,7
    cout<<*(*b+i)<<endl;   //output:1,2
}

 

posted on 2013-05-02 14:08  江在路上2  阅读(261)  评论(0编辑  收藏  举报