【C语言入门教程】4.6 指针 和 数组

数组在内存中以顺序的形式存放,数组的第一个存储单元的地址即数组的首地址。对一维数组来说,直接引用数组名就能获得该数组的首地址。指针变量可以存放于其内容相同的数组首地址,也可以指向某一具体的数组元素。通过这种方式,多维数组也被看作一维数组来操作,简化了数组的操作方式。

 

4.6.1 指针 与 一维数组

定义一维数组后,可定义一个与其类型相同的指针变量指向该数组。如:

int i[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, *pi;		// 定义整型数组 i 和整型指针变量 *pi
pi = i;		// 将指针变量 *pi 指向数组 i 的首地址

这样 *pi 就指向了数组 i 的第一个单元,该赋值操作等同于 “pi = &i[0]”,pi 与数组 i 的关系型如图 8.7 所示。如果对指针内的地址进行运输,指向“pi +=4”,则 pi 的指向关系随之发生改变,如图 8.8 所示。

因此,可以将 C 语言指针指向一维数组的方法总结为以下 3 条:

(1)、“pi + n”或“i + n”表示数组元素 i[n] 的地址,即“&i[n]”。数组 i 有 10 个元素,n 的取值为 0 至 9,则数组的地址可表示为“pi + 0”至“pi + 9”,或“i + 1”至“i + 9”,与 &i[0] 至 &i[9] 的作用一样;

(2)、知道了数组元素的地址表示方法,“*(pi + n)”;

(3)、指向数组的指针变量也可用数组的下标形式表示为 pi[n],其效果相当于“*(pi + n)”。

 

4.6.2 指针 与 二维数组

二维数组和其他多维数组都能看作一维数组进行指针操作 。如下例所示:

int i[2][5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, *pi; // 定义整型二维数组 i 和 整型指针变量 pi
pi = i[0]; // 将指针变量 pi 指向数组 i 的首地址

该数组可以视作一个表格,数组 i 与 pi 的关系如图 8.9 所示。如果要访问其中的元素 i[1][2],则可用公式 1 x n + 2 得到该元素的位置,引用时可写作 “*(pi + 1 * n + 2)”。

二维数组的每一行都有一个首地址,如 i[0] 代表 &i[0][0] 的地址,i[1] 代表 i[0][0] 的地址。因此,二维数组也可以看作是 m 个长度为 n 的一维数组,引用二维数组需要将每行的首地址赋给指针变量。如下例,用指针修改二维数组内的元素。

#include <stdio.h>				
#define M 2					// 定义常量 M,用作二维数组的行数
#define N 4 				// 定义常量 N,用作二维数组的列数

int main
{
	int a[M][N], *pa;
	int i, j;
	pa = a[0];									// 将指针变量 *pa 指向数组第 1 行的首地址
	printf("请输入数组的数值:");
	for (i = 0; i < M; i++)					
	{
		for (j = 0; j < N; j++)
		{
			scanf("%d", pa + i * N + j);		// 从键盘输入获取数据,保存到数组中
			putchar('\0');						// 换行
		}
	}
	
	printf("数组内的数值是:");
	for (i = 0; i < M * N; i++)
	{
		printf("%d\n", *(pa + i));				// 输出数组的值
	}
	
	return 0;
}

该代码首先将数组 a 的第一行首地址赋值给整型指针变量。第一组循环使用数组行和列的关系计算数组元素内存中的位置,给数组 a 的每个元素赋值。第二组循环通过指针变量 pa 间接引用数组 a 内的元素,将所有数组元素的数组输出。

 

4.6.3 指针 与 字符串数组

字符型指针变量指向字符串数组首地址后,该指针即可当作字符串使用。字符串处理函数通常根据字符串结束符判断该字符串的长度,所以这些函数都会延字符串首地址向后遍历,直到找到字符串结束符。下列用于简单的字符串输入与输出。

char c[20], *pc;		// 定义字符型数组 c 与 字符型指针变量 pc
pc = c;					// 字符型数组 c 的首地址赋给指针变量 pc
scanf("%19s", pc);		// 通过 pc 间接引用数组 c,为数组 c 初始化
puts(pc);				// 输出 pc 所指向的字符串

puts() 函数的作用是将字符串无格式输出,当 *pc 作为其参数时,会内存中将 *pc 所指向的地址开始,到字符串结束符之间的字符输出到终端。假如输入的字符串为“I love China!”,将代码最后一行改为:

puts(pc + 2);		// 输出内存中从 pc + 2 开始,到字符串结束符为止的字符串

那么,该程序的输出为 “love China”,因为 puts()函数会跳过字符串数组的前 2 个字符开始处理。如果字符数组中没有字符串结束符,则调用 printf() 或 puts() 输出函数后程序会出错(一直向后处理,输出很多意向不到的字符,直到遇到值为 0 的内存块)。如果字符型指针变量没有初始化,如下例所示:

char *pc;			// 字符型数组 c 的首地址赋值给指针变量 pc
scanf("%s", pc);	// 通过 pc 间接引用数组 c,为数组 c 初始化

这是一种非常危险的用法,因为 pc 的值不可知,pc 可能指向内存中的任意位置。将字符串保存到 pc 所指向的内存单元中,可能造成严重的系统错误。这种用法称之为无源指针,在程序中应避免出现。

posted @ 2016-07-18 15:19  52php  阅读(331)  评论(0编辑  收藏  举报