细说C++(六):关于数组和指针

关于数组和指针
 

指针类型总结

a) int a; // An integer

b) int *a; // A pointer to an integer

c) int **a; // A pointer to a pointer to an integer

d) int a[10]; // An array of 10 integers

e) int *a[10]; // An array of 10 pointers to integers

f) int (*a)[10]; // A pointer to an array of 10 integers

g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer

h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer 

 

 

 

1.数组 != 指针

char a[ ] char *a

数组定义 char a[6] 请求预留 6 个字符的位置, 并用名称 “a” 表示。 也就
是说, 有一个称为 “a” 的位置, 可以放入 6 个字符。

而指针申明 char *p, 请求一个
位置放置一个指针, 用名称 “p” 表示。 这个指针几乎可以指向任何位置: 任何字符
和任何连续的字符, 或者哪里也不指


例如声明
char a[] = "hello";
char *p = "world";
将会初始化下图所示的数据结果(内存区域示例图):


+---+---+---+---+---+---+
a: | h | e | l | l | o |\0 |
+---+---+---+---+---+---+
+-----+ +---+---+---+---+---+---+
p: | *======> | w | o | r | l | d |\0 |  
(指向一片内存区域)

 

根据 x 是数组还是指针, 类似 x[3] 这样的引用会生成不同的代码。

从 a 的位置开始跳过 3 个, 然后取出那个字符. 如果它看到 p[3], 它生成代码找到

“p” 的位置, 取出其中的指针值, 在指针上加 3 然后取出指向的字符。 换言之, a[3]是名为 a 的对象 (的起始位置) 之后 3 个位置的值, 而 p[3] 是 p 指向的对象的 3 个位置之后的值.

本质的区别在于类似 a 的数组和类似 p 的指针一旦在表达式中出现就会按照不同的方式计算!

 

2.指针和数组等价的条件

 (1)数组和指针的算法定义可以用指针方便的访问数组或者模拟数组

;从此层面上,数组和指针是等价可以共用的

说数组和指针 “等价”不表示它们相同, 甚至也不能互换。

 

一个 T 的数组类型的左值如果出现在表达式中会蜕变为一个指向数
组第一个成员的指针(除了三种例外情况); 结果指针的类型是 T 的指针。


这就是说, 一旦数组出现在表达式中, 编译器会隐式地生成一个指向数组第一
个成员地指针, 就像程序员写出了 &a[0] 一样。 例外的情况是, 数组为 sizeof 或 &
操作符的操作数, 或者为字符数组的字符串初始值。
作为这个这个定义的后果, 编译器并那么不严格区分数组下标操作符和指
针。 在形如 a[i] 的表达式中, 根据上边的规则, 数组蜕化为指针然后按照指针变量的方式如 p[i] 那样寻址,

尽管最终的内存访问并不一样。 如果你把数组地址赋给指针:
p = a; 那么 p[3] 和 a[3] 将会访问同样的成员。

 

3.作为函数形参的数组和指针声明可以互换

由于数组会马上蜕变为指针, 数组事实上从来没有传入过函数。 允许指针参
数声明为数组只不过是为让它看起来好像传入了数组, 因为该参数可能在函数内
当作数组使用。 特别地, 任何声明 “看起来象” 数组的参数, 例如
void f(char a[])
{ ... }
在编译器里都被当作指针来处理, 因为在传入数组的时候,那正是函数接收到
的.
void f(char *a)
{ ... }
这种转换仅限于函数形参的声明, 别的地方并不适用

 

 

4.多维数组

  (1)二维数组名为指向指针的指针

首先,通过优先级判断来确定它属性.

            int (*a)[1];  //  ()的优先级大于[],   因此p先于*结合,    (*p)是一个指针

            int *a[1];   //  *的优先级小于[],    因此p先于[]结合, p[4]是一个数组

           int *(a);    //   ()两个优先级相同, 因此从左到右按顺序执行,(*p)是一个指针

         int *a();     //    ()优先级高于*,    因此p先于()结合, p()是一个函数

然后,考虑:如果是指针,则考虑指针指向的内容

               如果是数组,则考虑数组的数据类型和长度

               如果是函数,则考虑函数的参数列表和返回值

               int (*a)[1];  //  指向数组的指针(数组指针)

               int *a[1];    //   指向指针的数组(指针数组)

              int *(a);     //    指向函数的指针(函数指针)

              int *a();     //    指向指针的函数 (指针函数)

 

 

5.指针数组和数组指针

(1)指针数组:它实际上是一个数组,数组的每个元素存放的是一个指针类型的元素。

 

int* arr[8];

//优先级问题:[]的优先级比*高

//说明arr是一个数组,而int*是数组里面的内容

//这句话的意思就是:arr是一个含有8和int*的数组

 

(2)数组指针:它实际上是一个指针,该指针指向一个数组。

 

int (*arr)[8];

//由于[]的优先级比*高,因此在写数组指针的时候必须将*arr用括号括起来

//arr先和*结合,说明p是一个指针变量

//这句话的意思就是:指针arr指向一个大小为8个整型的数组。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值