指针变量与数组的关系及什么是指针数组

指针变量与数组的关系及什么是指针数组:

  • 一维数组:

数组原本就是以指针的格式使用的,数组名a相当于char * const a。但这里需要注意的是数组名表示的是一个数组的首地址,是一个地址常量,不能给地址常量赋值,但能改变该地址所指向的内容,比如之前a首地址存放的内容为1,可以使用*a=2改变该地址单元里的内容。
在输出数组元素的值时一般以a[0]形式输出,该a[0]形式相当于**a、*(a+0)
char a[1],*p;
引用一维数组a的第i个元素,有下标法和指针法。假设指针变量p指向数组的首元素(p=a),则有四种数组元素的表示方法:
a[i] ↔ p[i] ↔ *(p(是变量)+i) ↔ *(a(是常量)+i)
a相当于c语言的宏替换#define a 地址常量。p是一个变量,是要把改变量所存放的地址常量取出来参加运算。

这里需要注意的是,指针变量和数组在访问数组中的元素时,一定条件下其使用方法具有相同的形式,因为指针变量和数组名都是地址量。但指针变量和数组的指针(或叫数组名)在本质上是不同的,数组在内存中的位置在程序运行过程中是无法动态改变的。因此,数组名是地址常量,指针是地址变量。数组名可以在运算中作为指针参与,但不允许被赋值。

  • 二维数组:

二维数组实际上是以一维数组的方式连续存放的,比如这里定义一个二维数组int c[2][2],可以把这二维数组当作是由两个一维数组组成的,然后我们在以一维数组的访问方式去访问数组元素,第一行的一维数组名为c[0],第二行的一维数组名为c[1]。这两个一维数组名与首数组名c类型一样,都是地址常量。首数组名c等于第一行一维数组名c[0], c+1就等于第二行的一维数组名c[1]。所以去访问二维数组也和一维数组一样。
这里定义一个指针int p=c[0]。
第一行:c[0][i] ↔ *(p+i) ↔ *(c[0]+i) ↔ *(*(c+0)+i) ↔ *(&c[0][0]+i)
第二行:c[1][i] ↔ *(c[1]+i) ↔ *(*(c+1)+i) ↔ *(&c[1][0]+i)
这里需要注意的是,
(c+1)的结果是第二行的首地址,不是该地址所指向的内容。也就是*(c+1)等价于c[1](前提是二维数组。在一维数组中*(a+1)返回的是地址所指向的内容,不是地址),这里实际也说明了数组本身就是以指针的形式去处理的。

指针数组:顾名思义,就是由同种类型的指针变量构成的数组。
比如有如下定义:
char p[2];
这里需要注意的是,由于“[ ]”的优先级高于“
”,所以,数组名p先于“[ ]”结合,构成一个数组形式,然后该数组在与“*”结合,构成指针数组形式。

这里说下指针数组名与非指针数组名的区别(一维数组举例):
非指针一维数组名的是地址常量,是一级指针形式。而指针的一维数组名也是一个地址常量,但该地址是二级指针形式。
之前我们知道了以为数组值可以用下标法引用,但也可以用指针法引用,比如:
a[1]等价于*(a+1)
所以引用指针数组元素可以使用:((p+i)),也就是**(p+i),或者*p[i]来引用。
指针数组首地址是二级指针地址常量,所以可以定义一个二级指针变量来指向该二级指针地址常量,即 char p1=p;或者也可以用p1=&p[0]来指向,这两种形式是一样的。

下面讲下如何使用指针数组来遍历非指针二维数组中的元素:
这里先定义一个字符二维数组:char c[2][2]={1,2,3,4};
然后再定义一个指针数组,将指针数组指向该字符二维数组:char *p[2]={ c[0] , c[1] };

那么,如何访问字符二维数组的第一行元素呢?
我们知道p[0]保存的是c[0]地址常量或者说保存的是&c[0][0],所以p[0]指向第一行第一列的内容,即值1。那么如何指向第一行第二列的值呢,很简单下,先用p[0]取出第一行第一列的地址,然后将地址加一,即p[0]+i,在将该地址的值取出,即(p[0]+i),然后我们知道p[0]也可以表示成*(p+0),所以又可以表示成*((p+0)+i),同理,第二行数组元素的值可以表示成(*(p+1)+i)。

    原文作者:wangjl~
    原文地址: https://blog.csdn.net/u013581207/article/details/93590626
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞