指针数组和数组指针

/*
int a[1024];   int*p=a;   a=&(a[0])   p=&(a[0])   p+0=&(a[0])   p+i=&(a[i])
*(p+i)=*(&(a[i]))=a[i]    *(p+i)=p[i]
*/
#include <iostream>
using namespace std;
#include <string>
string getHex(int x) {
    char buff[10];
    sprintf_s(buff, "%X", (x & 0xFFFF));
    return (string)buff;
}
/*
1.数组指针是一个值,不是数组
2.数组指针是指向整一个数组的,不是指向数组值
3.数组指针是二级指针,是地址的地址
*/

int main() {
    int a[3][4] = {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12}
    };
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 4; ++j) {
            if (j) {
                cout << ",";
            }int* p = &a[i][j];
            cout << getHex((int)p);
        }
        cout << endl;
    }
    int* q[3] = { a[0],a[1],a[2] };// {&a[0][0],&a[1][0],&a[2][0]};
    //数组指针
    int(*p)[4];
    p = &a[0];  //这个不能写成a[0]的形式,&a[0]是指整一行的首地址,而a[0]是指这一行数组首元素的首地址,二者值相同但意义不同

    cout << "1、指针+i" << endl;
    //q+i\p+i
    cout << "数组指针" << endl;
    for (int i = 0; i < 3; ++i) {
        string s = getHex((int)(p + i));
        cout << "第" << i << "个[4]数组的地址是" << s << endl;   
    }             //可以把数组指针看成一个二维数组,他只指向数组的每一行
    cout << "指针数组" << endl;
    for (int i = 0; i < 3; ++i) {
        string s = getHex((int)(q + i));
        cout << "第" << i << "个元素的地址是" << s << endl;      //这里的++i操作有取地址的操作,因为这是一个数组,数组的前置知识 
    }
    cout << "2、*(指针+i)" << endl;
    //*(q+i) \ *(p+i)
    cout << "数组指针" << endl;
    for (int i = 0; i < 3; ++i) {
        string s = getHex((int)*(p + i));
        cout << "a数组的第" << i << "行第0个元素的地址" << s << endl;//解引用后第0个元素的地址
    }
    //一般用数组的首元素地址来标识一个数组,所以*p是数组a本身,只不过用首元素地址来标志了
    //**p表示首元素的值
    cout << "指针数组" << endl;
    for (int i = 0; i < 3; ++i) {
        string s = getHex((int)*(q + i));
        cout << "a数组的第" << i << "行第0个元素的地址" << s << endl;
    }

      cout << "3、*(指针+i)+j" << endl;
      cout << "数组指针" << endl;
      for (int i = 0; i < 3; ++i) {
          string s = getHex((int)((*(p + i) + 1)));
          cout << "a数组的第" << i << "行第1个元素的地址" << s << endl;
      }
      cout << "指针数组" << endl;
      for (int i = 0; i < 3; ++i) {
          string s = getHex((int)((*(q + i) + 2)));
          cout << "a数组的第" << i << "行第2个元素的地址" << s << endl;
      }


    return 0;
}

1、指针+i
数组指针
第0个[4]数组的地址是F738
第1个[4]数组的地址是F748
第2个[4]数组的地址是F758
指针数组
第0个元素的地址是F7E8
第1个元素的地址是F7F0
第2个元素的地址是F7F8
2、*(指针+i)
数组指针
a数组的第0行第0个元素的地址F738
a数组的第1行第0个元素的地址F748
a数组的第2行第0个元素的地址F758
指针数组
a数组的第0行第0个元素的地址F738
a数组的第1行第0个元素的地址F748
a数组的第2行第0个元素的地址F758
3、*(指针+i)+j
数组指针
a数组的第0行第1个元素的地址F73C
a数组的第1行第1个元素的地址F74C
a数组的第2行第1个元素的地址F75C
指针数组
a数组的第0行第2个元素的地址F740
a数组的第1行第2个元素的地址F750
a数组的第2行第2个元素的地址F760
 

最后,从上文来看:

数组指针是一个指针变量,占有内存中一个指针的存储空间;

指针数组是多个指针变量,以数组的形式存储在内存中,占有多个指针的存储空间。

了解指针数组和数组指针二者之间的区别之后,继续来看下面的示例代码:

 
  1. int arr[5]={1,2,3,4,5};

  2. int (*p1)[5] = &arr;

  3. /*下面是错误的*/

  4. int (*p2)[5] = arr;

不难看出,在上面的示例代码中,&arr 是指整个数组的首地址,而 arr 是指数组首元素的首地址,虽然所表示的意义不同,但二者之间的值却是相同的。那么问题出来了,既然值是相同的,为什么语句“int(*p1)[5]=&arr”是正确的,而语句“int(*p2)[5]=arr”却在有些编译器下运行时会提示错误信息呢(如在 Microsoft Visual Studio 2010 中提示的错误信息为“a value of type"int*"cannot be used to initialize an entity of type"int(*)[5]"”)?

其实原因很简单,在 C 语言中,赋值符号“=”号两边的数据类型必须是相同的,如果不同,则需要显示或隐式类型转换。在这里,p1 和 p2 都是数组指针,指向的是整个数组。p1 这个定义的“=”号两边的数据类型完全一致,而 p2 这个定义的“=”号两边的数据类型就不一致了(左边的类型是指向整个数组的指针,而右边的数据类型是指向单个字符的指针),因此会提示错误信息。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值