计算机等级考试C语辅导:数组

计算机等级考试C语辅导:数组,第1张

计算机等级考试C语辅导:数组,第2张

C处理数组的方式是它受欢迎的原因之一。C语言对数组的处理非常有效,原因有以下三点:
第一,C语言中数组下标的处理是非常底层的,除了少数翻译人员出于谨慎会做出一些繁琐的规定。但这种优势也有一个负面影响,就是你无法知道一个数组有多大,也无法知道程序运行时一个数组下标是否有效。ANSI/ISOC标准没有定义使用越界下标的行为,因此一个越界下标可能导致以下后果:
(1)程序仍然可以正确运行;
(2)程序会异常终止或崩溃;
(3)程序可以继续运行,但无法得到正确的结果;
(四)其他情形。
换句话说,你不知道之后程序会有什么反应,这会造成很大的麻烦。有人拿这一点来批判C语言,认为C语言只是一种高级汇编语言。不过,虽然C程序出错的时候表现的很恐怖,但是谁也不能否认,一个精心编写调试的C程序运行起来是非常快的。
其次,数组和指针可以非常和谐地协同工作。当数组出现在表达式中时,它相当于指向数组中第一个元素的指针,所以数组和指针几乎可以互换使用。此外,使用指针比使用数组下标快一倍(见9.5中的例子)。
第三,将数组作为参数传递给函数完全
等同于将指向数组中第一个元素的指针传递给函数。将数组作为参数传递给函数时,有两种方式:值传递和地址传递。前者需要完全复制原数组,但更安全。后者要快很多,但是写程序的时候要小心。C++和ANSIC中都有const关键字,可以让地址传递和值传递一样安全。如果想了解更多细节,请参考2.4、8.6和第7章“指针和内存分配”开头的介绍。
数组和指针之间的这种联系会造成一些混淆,例如下面两个定义是相同的:
void f(chara[MAX])
{
/*...*/
}
void f(char * a)
{[/]
这种情况是上一篇文章提到的第三个优点,也是大多数C程序员所熟知的。这也是数组和指针完全相同的情况。在其他情况下,数组和指针并不完全相同。比如当取如下定义(可以出现在函数描述以外的任何地方):
char a[MAX];
内存的最大字符数空将由系统分配。如下描述:
char * a;
系统将为字符指针分配所需的内存空,它可能只能容纳2或4个字符。如果在源文件中定义了以下内容:
char a[max];
但在头文件中做如下解释;
extern char * a;
会导致可怕的后果。为了避免这种情况,方法是确保上述描述和定义的一致性。比如在源文件中做了如下定义:
char a[max];
然后,在对应的头文件中做如下解释,
extern char a[];
上面的描述告诉我们头文件A是一个数组,而不是一个指针,但是并没有说明数组A中有多少个元素,所以所描述的类型称为不完全类型。在程序中适当解释一些不完整的类型是很常见的,也是很好的编程习惯。
9.1数组的下标总是从0开始吗?
是的,对于数组a[MAX](MAX是编译时可知值),它的第一个和最后一个元素分别是a[o]和aLMAX-1。在其他语言中,情况可能有所不同。比如在BASIC语言中,数组a[MAX]的元素是从a[1]到a[MAX],而在Pascal语言中,两种方式都是可行的。
注意:a[MAX]是一个有效的地址,但是这个地址中的值不是数组A的元素(参见9。2)。
以上区别有时会造成混淆,因为当你说“数组中的第一个元素”时,实际上是指“数组中的下标是。元素”,这里“第一”的意思是“最后”的反义词。
尽管可以伪造下标从1开始的数组,但在实际编程中不应该这样做。下面将介绍这种技术,并解释为什么不应该这样做的原因。
因为指针和数组几乎一样,所以可以定义一个指针,让它像数组一样引用另一个数组中的所有元素,但是前者的下标从1开始:
/*不要这样!!*/
int a0[MAX],
int * a1 = A0-1;/*&A0 [-1] */
现在,a0[0]和a1[1]相同,而a0[MAX-1]和a1[MAX]相同。但是,实际编程中不应该这样做,原因有两个:
第一,这个方法可能行不通。ANSI/ISOC标准中没有定义这种行为(应该避免),并且&a0[-1]很可能不是有效地址(见9.3)。对于某些编译器来说,你的程序可能根本没有问题;在某些情况下,对于任何编译器,你的程序可能都没有问题;但是,谁能保证你的程序永远不会出错呢?
其次,这种方式背离了C语言的常规风格。人们已经习惯了C语言中数组下标的工作方式。如果你的程序用了另一种方式,别人就很难读懂你的程序。一段时间后,可能连你自己都很难读懂这个节目。
请看:
9.2我可以使用数组后第一个元素的地址吗?
9.3为什么我们要小心数组后面那些元素的地址呢?
9.2可以使用数组后第一个元素的地址吗?
可以使用数组后面第一个元素的地址,但不能查看该地址中的值。对于大部分编译器来说,如果你写下面的语句:
int i,a[MAX],j;
那么I和J可能都存储在数组A最后一个元素之后的地址中,要判断I或J是否跟在数组A之后,可以将I或J的地址与数组A之后的第一个元素的地址进行比较,即判断“&i==&a[MAX]”或“&j==&a[MAX]”是否为真。这种方法通常是可行的,但不能保证。
问题的关键在于:如果你在a[MAX]中存储一些数据,往往会破坏紧跟在数组a之后的数据,即使是看a[MAX]的值也要避免,虽然这通常不会导致任何问题。
为什么C程序中有时会用到&a[MAX]?因为很多C程序员习惯用指针遍历一个数组中的所有元素,也就是用
for(I = 0;I {
/*做某事*/
}
而不是
for(p = a;P {
/*做点什么*/
}
这种方法在现有的C程序中随处可见,所以ANSIC标准规定这种方法是可行的。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 计算机等级考试C语辅导:数组

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情