zoukankan      html  css  js  c++  java
  • 指针和引用(3)指针数组和数组指针

    1.知识点

    1.1指针数组——存放指针的数组

    (1)指针数组本质上是一个数组,指针是数组中的内容,表示数组中的每个元素都是指针,因此指针数组就是存放指针的数组。下面是指针数组的用法:

    1 int a = 10, b = 20;
    2 int *p[3];
    3 p[0] = &a;
    4 p[2] = &b;

    (2)指针数组的定义可以抽象为:指向变量类型 * 数组名称[数组长度]。

    (3)[]的优先级高于*,所以[]与p先结合,说明p是一个数组,长度为3,其数组元素的类型是int *。

    1.2数组指针——指向数组的指针

    (1)数组指针本质上是一个指针,数组是指针指向的类型,表示指针指向一个数组,因此数组指针就是指向数组的指针。下面是数组指针的用法:

    1 int a[3] = { 1,2,3 };
    2 int (*p)[3];
    3 p = &a;

    (2)数组指针的定义可以抽象为:数组元素类型 (* 指针名称)[数组长度]。

    (3)()使得*与p先结合,所以p是一个指针,盖掉(*p)剩下的就是指针指向的内容了即int[3]。

    (4)数组指针指向整个数组a(取地址&a),而非数组a的首元素(取地址a),虽然数组a和数组a中首元素的地址相同。

    2.面试题

    2.1简述数组指针与二维数组的区别

    请写出下面程序的输出结果(假设数组a的地址&a为0x001DF720)

     1 int main(int argc, char *argv[]) {
     2     //数组指针和二维数组的区别
     3     int a[2][5] = { {1,2,3,4,5},{6,7,8,9,10} };
     4     int(*p)[5] = a;
     5     cout << p << endl;
     6     cout << p + 1 << endl;
     7 
     8     cout << *p << endl;
     9     cout << *(p + 1) << endl;
    10     cout << *p + 1 << endl;
    11 
    12     cout << **p << endl;
    13     cout << **(p + 1) << endl;
    14     cout << *(*p + 1) << endl;
    15 
    16     getchar();
    17     return 0;
    18 }

    知识点提示:(1)数组名始终等价于数组首元素的地址:a<=>&a[0]。

    (2)解引用的次数等于数组的维度时,才能得到数组的元素值,如二维数组必须经过两次解引用才能得到数组的元素值。

    (3)数组首元素地址和数组的地址虽然位置一样,但是二者完全不是一回事(通过解引用来理解),数组首元素地址&a[0]解引用之后为*(&a[0])=a[0],是首元素的值;而数组地址&a解引用之后为*(&a)=a=&a[0];通过以上说明,数组地址一次解引用之后得到数组首元素的地址,再解引用之后得到首元素的值(在一维数组的情况下)。

    (4)二维数组a[n][m],可以把a[n]看成是内层[m]的数组名。

    按照以上的知识和规则认真分析可以得出如下答案:

     1 //数组a的地址&a为0x001DF720
     2  int main(int argc, char *argv[]) {
     3      int a[2][5] = { {1,2,3,4,5},{6,7,8,9,10} };
     4      int(*p)[5] = a;//a==&a[0],左右类型相同,p指向一个元素为5的一维数组
     5      cout << p << endl;//两次解引用是地址,p=&a[0],0x001DF720
     6      cout << p + 1 << endl;//两次解引用是地址,p+1=&a[1]=0x001DF720+4*5=0x001DF734
     7   
     8      cout << *p << endl;//一次解引用是地址,*p=a[0]=&a[0][0],0x001DF720
     9      cout << *(p + 1) << endl;//一次解引用是地址,*(p+1)=a[1]=&a[1][0],0x001DF734
    10      cout << *p + 1 << endl;//一次解引用是地址,*p+1=&a[0][1]=0x001DF724
    11  
    12      cout << **p << endl;//二次解引用是元素值,**p=a[0][0]=1
    13      cout << **(p + 1) << endl;//二次解引用是元素值,**(p+1)=a[1][0]=6
    14      cout << *(*p + 1) << endl;//二次解引用是元素值,*(*p+1)=a[0][1]=2
    15  
    16      getchar();
    17      return 0;
    18  }

    2.2简述数组地址和数组首地址的区别

    指出下面程序中的错误:

    1 int main(int argc, char *argv[]) {
    2     int b[6] = { 1,2,3,4,5,6 };
    3     int *p = &b;  //左右类型不匹配
    4     cout << p << endl;
    5 
    6     getchar();
    7     return 0;
    8 }

    知识点:数组首元素地址和数组的地址虽然位置一样,但是二者完全不是一回事(通过解引用来理解),数组首元素地址&a[0]解引用之后为*(&a[0])=a[0],是首元素的值;而数组地址&a解引用之后为*(&a)=a=&a[0];通过以上说明,数组地址一次解引用之后得到数组首元素的地址,再解引用之后得到首元素的值(在一维数组的情况下)。

    修改方式以下二选其一:

    1 //方式一
    2 int (*p)[6]=&b;
    3 //方式二
    4 int *p=b;//或者:int *p=&b[0];

    2.3简述指针数组与指向指针的指针的区别

    写出指针数组str中四个指针元素的值。

    由于题目有问题,未正确解答,故略。

  • 相关阅读:
    机器学习---聚类算法
    机器学习解决问题的框架
    17个机器学习的常用算法!
    机器学习---理论篇
    golang 调用cmd执行EXE
    队列(自定义列表实现自定义队列)
    栈Stack(使用自定义链表实现自定义栈)
    链表( 自定义链表)
    队列(动态数组实现自定义队列)
    栈Stack(动态数组实现自定义栈)
  • 原文地址:https://www.cnblogs.com/ys99/p/9195371.html
Copyright © 2011-2022 走看看