C/C++数组指针和指针数组

数组指针和指针数组的区别

指针数组:首先它是一个数组,每一个元素都是一个指针。

数组指针:首先它是一个指针,它指向一个数组。它是"指向数组的指针"的简称。

运算符的优先级关系:() > [] > *

 

数组指针(也称行指针)
例如:int (*p)[n];
根据优先级,先看( )内,p是一个指针,后面的[ ]又说明了p是一个指向数组的指针,由于前面的int,所以p是一个指向 int 类型数组的一个指针。

将二维数组赋给指针:

int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a;         //将该二维数组的首地址赋给p
p++;         //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针。

 

指针数组
例如: int *p[n];
根据优先级,p先与[ ]结合所以p是一个数组,再结合 *,表明数组里面的元素是指针,再加上int,说明p数组中的元素是int类型的指针。

将二维数组赋给指针数组:

int *p[3];
int a[3][4];
p++;              //该语句表示p数组指向下一个数组元素。

for(i=0;i<3;i++)
    p[i]=a[i]
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]所以要分别赋值。

在二维数组里面
a,&a,a[0],&a[0],&a[0][0]五个值是一样的,都指向二维数组的首地址(起始位置)。区别在于这五种表达方式的类型是不同的,以int a[2][3]举例:
a是二维数组名,是常量,存放着二维数组的首地址,类型为二维数组,sizeof(a)=24。
&a 二维数组a的(首)地址,本身是一个指针,sizeof(&a)=4,指针类型都为4。
a[0]指向二维数组中的第一行数组a[0][],类型是一维数组sizeof(a[0])=12。
&a[0]代表a[0]的地址,与一维数组名a[0]值相同,但本身是指针类型sizeof(&a[0])=4。
&a[0][0]表示二维数组中第一个元素的地址,指针类型sizeof(&a[0][0])=4。

 

A和&A之间的区别

分析如下代码:

int main()
{
    char a[5]={'A','B','C','D'};
    char (*p3)[5] = &a;
    char (*p4)[5] = a;
    return 0;
}

上面对p3 和p4 的使用,哪个正确呢?p3+1 的值会是什么?p4+1 的值又会是什么?毫无疑问,p3 和p4 都是数组指针,指向的是整个数组。&a 是整个数组的首地址,a是数组首元素的首地址,其值相同但意义不同。在C/C++里,赋值符号“=”号两边的数据类型必须是相同的,如果不同需要显示或隐式的类型转换。p3 这个定义的“=”号两边的数据类型完全一致,而p4 这个定义的“=”号两边的数据类型就不一致了。左边的类型是指向整个数组的指针,右边的数据类型是指向单个字符的指针。在Visual C++6.0 上给出如下警告:

warning C4047: 'initializing' : 'char (*)[5]' differs in levels of indirection from 'char *'。

这里给出了警告,可是由于&a 和a 的值一样,而变量作为右值时编译器只是取变量的值,所以运行并没有什么问题。虽然能运行,但不能这么用。

现在清楚了p3 和p4 都是指向整个数组的,那p3+1和p4+1的值就很好理解了。测试代码如下:

#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
    char a[5]={'a','b','c','d'};
    char (*p1)[5]= &a;
    char (*p2)[5]=(char (*)[5])a;

    printf("a = %p\n",&a);          //%p打印数组地址
    printf("a = %c\n",a[0]);
    printf("p1 = %c\n",**p1);
    printf("p2 = %p\n",*p2);
    printf("p1+1 = %p\n",*(p1+1));  //p1是数组指针,数组a的长度是5个字节,所以p1+1将指向a[0]向后移动5个字节的位置
    printf("p2+1 = %p\n",*(p2+1));  

    return 0;
}



结论:根据指针类型及所指对象,表示指针大小,每次加1,表示增加指针类型大小的字节

 

另一个实例

#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
    int a[4]={1,2,3,4};
    int *ptr1=(int *)(&a+1);         //指向a数组后面的内存单元,&a+1表示向后移16个存储单元
    int *ptr2=(int *)(a+1);          //表示a的存储单元的地址增加一个字节
    printf("%d,%d",ptr1[-1],*ptr2);  //ptr1[-1]其实指向的是a数组的最后一个单元
    return 0;
}

其内存布局如下图:

参考:https://www.cnblogs.com/mq0036/p/3382732.html

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页