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

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 所指向的内存单元中,可能造成严重的系统错误。这种用法称之为无源指针,在程序中应避免出现。

【C语言入门教程】4.6 指针 和 数组的更多相关文章

  1. 【C语言入门教程】4.1 一维数组

    数组与指针涉及到数据在内存中的存储位置问题,数组由连续的存储单元组成,最低地址对应于数组的第一个单元,最高地址对应于数组的最后一个单元.指针是一种特殊的变量,该变量所存放的是内存地址,通过指针变量可访 ...

  2. 《Ruby语言入门教程v1.0》学习笔记-01

    <Ruby语言入门教程v1.0> 编著:张开川 邮箱:kaichuan_zhang@126.com 想要学习ruby是因为公司的自动化测试使用到了ruby语言,但是公司关于ruby只给了一 ...

  3. C语言入门教程-(5)格式化输入输出

    1.输入和输出 在程序的使用中,我们经常可以看的这么一个场景:用户需要输入数据,经过程序运算,得到结果后输出.在C语言中,输入数据和输出数据都是由库函数完成的,通过语句来输入/输出. 2.格式化输出— ...

  4. Go语言入门教程(十)之函数

    Hello 各位小伙伴大家好,我是小栈君,假期一眨眼就过去了.不知道大家玩的是否开心呢? 上次我们讲到了关于Go语言的流程控制,小栈君也希望小伙伴跟着小栈君一步一个脚印的敲一下代码,相互进步.本期我们 ...

  5. c语言该怎么入门?C语言入门教程(非常详细)

    C语言是一门面向过程的编译型语言,它的运行速度极快,仅次于汇编语言.C语言是计算机产业的核心语言,操作系统.硬件驱动.关键组件.数据库等都离不开C语言:不学习C语言,就不能了解计算机底层. 这套「C语 ...

  6. 《JavaScript语言入门教程》记录整理:入门和数据类型

    目录 入门篇 js介绍 历史 基本语法 数据类型 概述 null 和 undefined 数值 字符串 对象 函数 数组 本系列基于阮一峰老师的<JavaScrip语言入门教程>或< ...

  7. 《JavaScript语言入门教程》记录整理:运算符、语法和标准库

    目录 运算符 算数运算符 比较运算符 布尔运算符 二进制位运算符 void和逗号运算符 运算顺序 语法 数据类型的转换 错误处理机制 编程风格 console对象和控制台 标准库 Object对象 属 ...

  8. 《JavaScript语言入门教程》记录整理:面向对象

    目录 面向对象编程 实例对象与 new 命令 this关键字 对象的继承 Object对象的方法 严格模式(strict mode) 本系列基于阮一峰老师的<JavaScrip语言入门教程> ...

  9. Go 语言入门教程,共32讲,6小时(已完结)

    Go语言入门教程,共32讲,6小时(完结) 在B站:https://www.bilibili.com/video/BV1fD4y1m7TD/

  10. 【C语言入门教程】7.3 结构体指针的定义和引用

    C 语言中指针的操作非常灵活,它也能指向结构体变量对结构体变量进行操作.在学习结构指针之前,需要再次加深对指针的认识.声明指针变量时所使用的数据类型修饰符实际上的作用是定义指针访问内存的范围,如果指针 ...

随机推荐

  1. 【Beta】Daily Scrum 第一天

    [目录] 1.任务进度 2.困难及解决 3.燃尽图 4.代码check-in 5.总结 1. 任务进度 学号 已完成 接下来要完成的 612 添加计时界面返回按键事件,添加SharePreferenc ...

  2. PL/0编译器(java version) – Scanner.java

    1: package compiler; 2:   3: import java.io.BufferedReader; 4: import java.io.FileNotFoundException; ...

  3. HTML5学习总结-03 地理定位

    一 地理定位 HTML5 Geolocation(地理定位)用于定位用户的位置. 1 地理定位 地理位置 经度  :   南北极的连接线 纬度  :   东西连接的线 位置信息从何而来: IP地址 G ...

  4. sql 行转 列, 列转行

    行列互转 复制代码 create table test(id ),quarter int,profile int) insert into test values(,,) insert into te ...

  5. Java排序算法——插入排序

    import java.util.Arrays; //================================================= // File Name : Select_S ...

  6. JAVA 5.17习题

    1.编写并测试一个代表地址的Address类,地址信息由国家.省份.城市.街道.邮编组成,并可以返回完整的地址信息. //======================================= ...

  7. JSP EL表达式

    1 EL表达式简介 EL 全名为Expression Language.EL主要作用: 1.获取数据 EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象.获取数 ...

  8. JSON FX

    https://github.com/mckamey/jsonfx-v1#svn/trunk/JsonFx/JsonFx.Json

  9. memcache相同主域名下的session共享

    本配置适合具有相同主域名的多台服务器进行session共享. 例如:www.lee.com , bbs.lee.com(多个子域名). 配置session保存在memcache: ini_set(&q ...

  10. The method below converts an array of objects to a DataTable object in C#.

    http://www.c-sharpcorner.com/blogs/dynamic-objects-conveting-into-data-table-in-c-sharp1 public stat ...