知方号

知方号

C/C++基础

C/C++基础 -- 指针与数组、字符串 1、一维数组和指针1.1、一维数组的地址1.2、指向一维数组的指针变量1.3、通过指针访问一维数组元素 2、二维数组和指针2.1、二维数组的地址二维数组的首地址和数组名 2.2、指向二维数组的指针变量2.3、通过指针访问二维数组的元素 3、字符串和指针(char型指针,c语言描述)3.1、字符串指针的定义3.2、通过指针访问字符串3.3、指针访问二维字符串

本博文由 西北工业大学MOOC 总结而来,以备以后回顾。 此次二维数组为自己增加的内容,如有错误欢迎留言指正

1、一维数组和指针 1.1、一维数组的地址

  数组由若干元素组成,每个元素都有相应的地址,通过取址运算符(&)可以得到每个元素的地址。   C++规定,数组名既代表数组本身,又代表整个数组的地址,还是数组首元素的地址。即a与a的第0个元素的地址&a[0]相同。例如,   数组名是一个指针常量,因为不能出现在左值和某些算术运算中,例如:

1.2、指向一维数组的指针变量

  定义指针时,用数组名初始化指针,即可将指针指向一维数组。指针的指向类型应和数组元素类型一致。例如:

1.3、通过指针访问一维数组元素

  由于数组元素的地址是规律性增加的,更具指针算术运算规则,可以利用指针及其运算来访问数组元素。   访问一维数组元素有以下四种方法:

2、二维数组和指针 2.1、二维数组的地址

  假如有一个二维数组:

int a[3][4] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}};

  其中,a 是二维数组名。a 数组包含 3 行,即 3 个行元素:a[0],a[1],a[2]。每个行元素都可以看成含有 4 个元素的一维数组。而且 C 语言规定,a[0]、a[1]、a[2]分别是这三个一维数组的数组名。如下所示:   a[0]、a[1]、a[2] 既然是一维数组名,一维数组的数组名表示的就是数组第一个元素的地址,所以 a[0] 表示的就是元素 a[0][0] 的地址,即

a[0] == &a[0][0];a[1] == &a[1][0];a[2] == &a[2][0];

  所以二维数组 a[M][N] 中,a[i] 表示的就是元素 a[i][0] 的地址,即

a[i] == &a[i][0];

  则 a[i]+j 就表示元素 a[i][j] 的地址,即:

a[i]+j == &a[i][j];

  同时由一维数组 a[i] 和 *(a+i) 等价,引申至二维有:

*(a+i)+j == &a[i][j]; 二维数组的首地址和数组名

  二维数组就是一维数组,二维数组 a[3][4] 就是有三个元素 a[0]、a[1]、a[2] 的一维数组,所以二维数组 a[3][4] 的第一个元素不是 a[0][0],而是 a[0] (第一行元素的地址),所以数组名 a 表示的不是元素 a[0][0] 的地址,而是 a[0] 的地址,即:

a == &a[0];//数组名代表数组第一行元素a[0]的地址

而 a[0] 又是 a[0][0] 的地址,即:

a[0] == &a[0][0];

则二维数组名 a 和 元素名 a[0][0] 的关系是:

a == &(&a[0][0]);//数组名代表数组第一行元素a[0]的地址

  二维数组的空间在内存中也是连续的地址。对于内存而言,没有维度而言,内存是一维的,内存里面不分行也不分列,元素都是按顺序一个一个往后排的,所以二维数组中的每一个元素在内存中的地址都是连续的。如下: 定义一个二维数组:

int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};或int a[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };

按行输出为:

1 2 3 45 6 7 89 10 11 12

其元素的地址输出为:

0X18FF18 0X18FF1C 0X18FF20 0X18FF240X18FF28 0X18FF2C 0X18FF30 0X18FF340X18FF38 0X18FF3C 0X18FF40 0X18FF44

可以看出二维数组元素的地址在内存中是连续存在的。

2.2、指向二维数组的指针变量

  前面提到过,二维数组是由一行一行的一维数组组成的,如 a[0]、a[1],a[2];同时也是由一个一个的单独的元素组成的,如 a[0][0]、a[1][1]、a[2][2]。所以指向二维数组的变量可以有两种形式: 1)行指针:(常用) 行指针的定义如下,其指向的是二维数组的第0行。形式如下:

指针类型 (*指针名称)[数组列数] = 数组名/数组第0行元素地址;int a[M][N] = {.......};int (*p)[N] = a; //其中N是二维数组a[M][N]的列数, 是一个数字。或//**数组长度不能定义成变量int (*p)[N] = &a[0];//a == &a[0];//***************注意与指针数组作区别,int *p[4] 为指针数组,//其中包含四个int型指针,即p[0],p[1],p[2],p[3]都是int型指针,其中存储的都是地址值

2)列指针: 列指针指向二维数组的第0个元素,其在形式上与指向单一对象的指针没有区别。形式如下:

指针类型 *指针名称 = 数组第[0][0]元素;int a[M][N] = {.......};int *p = &a[0][0];//指向二维数组第0行第0列的元素

  注意这两种指针都是一个指针,应与指针数组做区别(由多个指针元素组成的数组)。且指向二维数组的两种指针不能弄混,是因为二维数组的组成既是由行元素组成,也是由单个元素组成。行指针只能指向数组的行(一般指向第0行),其定义必须包含数组的列长度;列指针只能指向某一个元素,其相当于一个指向单独对象的指针。

2.3、通过指针访问二维数组的元素

1)行指针:(常用)   定义一个二维数组和指向该数组的指针:

int a[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };int (*p)[4] = a;//将指针指向二维数组a的首地址

则有如下的取值方式:

*(*(p+i)+j) == a[i][j];

  括号的运算优先级最高,所以最先运算 p+i,将指针指向第 i 行,再运算 * 号解引用得到第 i 行的首地址 &a[i],再运算 &a[i]+j,将指针指向第 i 行 第 j 列的元素的地址&a[i][j],再运算 * 号解引用得到元素的值 a[i][j]。   同理,还有其他取值方式:

*(*p) == *(a[0]) == *(&a[0][0]) == a[0][0];//value = 1*(*p+1) == *(a[0]+1) == *(&a[0][1]) == a[0][1];//value = 2*(*(p+1)) == *(a[0+1]) == *(&a[1][0]) == a[1][0];//value = 5*(*(p+1)+2) == *(a[1]+2) == *(&a[1][2]) == a[1][2];//value = 7

2)列指针:   列指针的实质是一个指向单独元素的指针,利用二维数组在存储空间上的连续性,也可对通过相应操作取得相应的值。举例如下:

# include int main(void){ int a[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; int i, j; int *p = &a[0][0]; //把a[0][0]的地址赋给指针变量p for (i=0; i

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。