高质量程序设计指南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 }