指向常量的指针与指针常量
指针常量:
int *const p=&i
特点:无法改变指向,但是可以改变指向的内容
指向常量的指针:
int const * p =&i
特点:可以改变指向,但是不能通过指针修改内存内容
指针常量指向常量
int const * cost p=&i
特点:既不能改变指向,也不能修改内容
总结:在不涉及到指针的情况下,int const 和const int 的效果是相同的,但是如果涉及到指针,const在 * 后面,表示指针常量,在 * 前面表示指向常量的指针,如果有 * 在两个const 之间,那个这个指针是常量,同时指向的数据也是常量!
指针与一维数组
对于一个一维数组来说,数组名就是其第一个元素的地址
int *p=a 等价于 int *p=&a[0]
指针与二维数组
因为二维数组和一维数组的内存地址都是连续的,可以将二维数组中看成一维数组
用指针遍历二维数组:
int *p=a[0]
for(int i=0;i
对于二维数组来说
int a[4][3]={1,2,3,4,5,6,7,8,9,10,11,12}
cout<
这五种的输出情况都是一样的,输出的都是二维数组第一个元素的地址,即a[0][0]的地址
,但是这里有一个比较不同的点,就是 a和*a输出的结果是一样的,加上 * 之后值是不变的
int *p=a; //无法从 int [4][3]转化为 int *,因为维度不匹配
int *p=&a[0]; //无法从 int (*)[3] 转化为int *,因为维度不匹配
int *p=*a; //可以正常编译,↓
int *p=&a[0][0];
int *p=a[0];
cout<<**a<
对于二维数组的数组名a来说,加两个*,才能表示数组第一个元素的值,第一个 * 是找到二维数组中一维数组的首地址,第二个 * 才是从一维数组的地址中找到首个元素的值,对于一个x维的数组来说,要在数组名前面加上x个 * 才能表示数组第一个元素的值
使用单一的普通指针时
类推:
对于一维数组来说
int *p=a等价于 int *p=&a[0],
但是一旦a变成二维数组之后,这两条编译就不过了,变成
int *p=a[0] 等价于 int *p=&a[0][0] 等价于 int *p=*a
如果是三维数组的话,上面三条又会编译错误,变成
int *p=a[0][0]等价于 int *p=&a[0][0][0] 等价于 int *p=**a;
值得注意的二维数组指针表示:
a+n //表示数组第n行的首地址
a[0]+n //表示第0行,第n个元素的地址
a[n]+m //表示第n行,第m个元素的地址
*(*(a+n)+m) //表示第n行第m列的元素!
类比3/多维数组
*(*(*(a+n)+m)+k) //表示坐标为(n,m,k)的元素
数组指针与指针数组
数组指针:
int (*a)[4];
// *和数组名一起被括号括起来,这是一个指针,指向的是一个大小为4的数组
int *a[4]; //这个就比较浅显,跟数组指针的区别就是*和数组名没被括号括起来
我们刚才使用一个普通的指针 int *p指向二维数组的数组名a时,(int *p=a)显然是编译错误的,但是如果这是一个数组指针,就是可以的
int a[4][3];
int (*p)[3]=a; //一个大小为3的数组指针!,这样是不会编译错误的!
for(int i=0;i<4;i++)
{
for(int j=0;j<3;j++)
{
cout<<*(*(p+i)+j)<<" "; //输出二维数组的的内容
}
}