指针数组和数组指针及相关概念

来源:互联网 发布:金融管理信息系统软件 编辑:程序博客网 时间:2024/05/20 18:03

概述

  • 指针数组:指存在一个数组,里面的元素类型是指针类型。例如int* num[10];
  • 数组指针:指存在一个指针,指向一个数组。例如 int (*p)[10];

也就是说,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。

需要注意的是,优先级:() > [] > *

举例

#include <bits/stdc++.h>using namespace std;int main(){    char s[5] = {'A', 'B', 'C', 'D'};    char (*p)[5] = &s;    char (*q)[5] = (char (*)[5])s;//为什么要做强制类型转换?    cout<<&s<<"  "<<s<<"  "<<*s<<endl;    cout<<&p<<"  "<<p<<"  "<<*p<<endl;    cout<<&q<<"  "<<q<<"  "<<*q<<endl;    char* r[5];    for(int i = 0; i < 4; ++i)        r[i] = &s[i];    cout<<&r<<"  "<<r<<"  "<<*r<<endl;    for(int i = 0; i < 4; ++i)        cout<<&r[i]<<"  "<<r[i]<<"  "<<*r[i]<<endl;    return 0;}

上述代码输出结果为:

0x6afee3  ABCD  A0x6afedc  0x6afee3  ABCD0x6afed8  0x6afee3  ABCD0x6afec4  0x6afec4  ABCD0x6afec4  ABCD  A0x6afec8  BCD  B0x6afecc  CD  C0x6afed0  D  D

从上述输出结果来分析,不难发现我们在内存中为字符数组分配了一部分空间来存储字符串“ABCD”,其首地址为 0x6afee3,所以当我们输出&s时,输出的是 0x6afee3,输出s时,输出的是字符串“ABCD”,但是当我们在输出*s时,为什么输出的是 “A”呢?实际上&ss的值相同但意义不同,前者是数组的首地址,后者是数组首元素的地址,即前者的类型是char (*)[5]后者的类型是char*,故输出前者是输出该数组中的字符串(ABCD),输出后者是输出该数组的首元素(A)。这也就是为什么不能写成char (*q)[5] = s;而是要做强制类型转换。,如若不然编译器会报错。
对于数组指针p和q来说,他们各自有自己的存储空间,也就是有各自的地址,但是他们都指向s,所以其存储空间里面存放的时s的地址,所以当我们输出&p、p、*p&q、q、*q)时实际上是输出数组指针p(q)的地址、p(q)所指的地址(即s的地址)、p(q)所指地址的存储空间里面的内容(即s的内容)。
对于指针数组r而言,赋值语句让r中的元素分别存放的是s中元素的地址。当我们输出&r时,实际上输出的是数组r的首地址,输出r时,输出的是首元素的地址(同理两个值相等但是类型不同),输出*r时,则输出字符串“ABCD”,这是因为r的首元素中存放的就是数组s的首地址。
那么在循环输出时,每一步的输出就不难解释了,这里不再赘述。

练习

声明一个指向含有10个元素的数组的指针,其中每个元素是一个函数指针,该函数的返回值是int,参数是int*,正确的是()
A.(int *p[10])(int*)
B.int [10]*p(int *)
C.int (*(*p)[10])(int *)
D.int ((int *)[10])*p

答案:C
先看未定义标识符p,p的左边是*,*p表示一个指针,跳出括号,由于[]的结合性大于*,所以*p指向一个大小为10的数组,即(*p)[10]。左边又有一个*号,修释数组的元素,*(*p)[10]表示*p指向一个大小为10的数组,且每个数组的元素为一个指针。跳出括号,根据右边(int *)可以判断(*(*p)[10])是一个函数指针,该函数的参数是int*,返回值是int,所以选C。

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