第4章 指针和数组
数组是C内建的基本数据结构,彻底理解数组及其用法是开发高效应用程序的基础。曲解数组和指针的用法会造成难以查找的错误,应用程序的性能也难以达到最优。数组和指针表示法紧密关联,在合适的上下文中可以互换。
一种常见的错误观点是数组和指针是完全可以互换的。尽管数组名字有时候可以当做指针来用,但数组的名字不是指针。数组表示法也可以和指针一起使用,但两者明显不同,也不一定能互换。理解这种差别可以帮助你避免错误地使用这些表示法。比如说,尽管数组使用自身的名字可以返回数组地址,但是名字本身不能作为赋值操作的目标。
数组在应用程序中随处可见,可能是一维,也可能是多维。在本章中,我们会讲解数组跟指针相关的基础知识,以便你深入理解数组以及使用指针操作数组的各种方法。本书其他章节还会展示在更高级的环境中使用数组和指针。
本章首先概述数组,然后研究数组表示法和指针表示法的相同点和不同点。可以用malloc类函数创建数组,这些函数提供比传统的数组声明更灵活的机制。我们会看到如何用realloc函数来改变已经为一个数组分配的内存大小。
为数组动态分配内存可以为代码带来很大的改变,特别是处理二维或多维数组的情况,因为我们得确保为数组分配的内存是连续的。我们也会探索传递和返回数组时可能发生的问题。大部分情况下,必须传入数组长度以便函数正确处理数组。数组的内部表示不带有长度信息,如果我们不传递长度,函数就没有标准的方法得到数组的终点。即便并不常用,我们也会研究如何在C中创建不规则数组。不规则数组是二维数组,每一行都可能包含不同的列数。要说明这些概念,需要使用向量和矩阵,前者代表一维数组,后者代表二维数组。向量和矩阵用途广泛,包括电磁场分析、天气预报和数学上的应用。
4.1 数组概述
数组的概念:相同数据类型的数据的集合,可以通过索引进行访问。有一维数组/二维数组.....
a.二维数组,一般用行和列来表述数组元素的位置。
b.切记不要混淆二维数组和指针的数组。
c.变长数组技术:变长数组的技术是用realloc函数实现的。
变长数组的能解决的问题:
数组的长度是固定的,当我们声明数组时,需要决定该数组有多大。如果指定过多元素就会浪费空间,而指定过少元素就
会限制能够处理的元素数量。
realloc函数和变长数组提供了应对长度需要变化的数组的技术。只要略施小计,我们就能调整数组长度,只占用合适的内存。
数组是能用索引访问的同质元素连续集合。这里所说的连续是指数组的元素在内存中是相邻的,中间不存在空隙,而同质是指元素都是同一类型的。数组声明用的是方括号集合,可以拥有多个维度。
4.1.1 一维数组
一维数组是线性结构,用一个索引访问成员。下面的代码声明了一个5个元素的整数数组:
int vector[5]; //数组索引从0开始,到声明的长度减1结束。vector数组的索引从0开始,到4结束。
数组越界:C并没有强制规定边界,用无效的索引访问数组会造成不可预期的行为。
下图说明了数组的内存如何分配,每个元素4字节长,且没有初始化。取决于不同的内存模型,数组的长度可能会不同。数组的内部表示不包含其元素数量的信息,数组名字只是引用了一块内存。
对数组做sizeof操作会得到为该数组分配的字节数,要知道元素的数量,只需将数组长度除以元素长度,如下所示,打印结果是5:printf("%d\n", sizeof(vector)/sizeof(int));
可以用一个块语句初始化一维数组,下面的代码把数组中的元素初始化为从1开始的整数:int vector[5] = {1, 2, 3, 4, 5};
4.1.2 二维数组
4.1.3 多维数组
4.2 指针表示法和数组
数组和指针的差别