c#发展

首页 » 常识 » 常识 » C语言陷阱与技巧第14节,数组操作的一些
TUhjnbcbe - 2024/3/31 9:11:00

数组是大多数编程语言中非常重要的语法,在C语言中尤为如此,可以认为C语言中的数组是一种复合数据类型——若干数据类型元素组合而成的集合。

之前的文章讨论过,数据结构决定代码逻辑和算法,换句话说也就是决定可以处理什么样的问题。C语言中的数组特别适合存储大量相同类型的元素,而且数组的各个元素在内存中是紧密排列的,因此各个元素的地址都可知,所以C语言程序可以随机访问数组元素,这使得排序、查找最值等问题变得方便。

数组的定义和使用

在C语言中定义一个数组是方便的,上面说到数组是“若干数据类型元素组合而成的集合”,因此可以如下定义数组:

数据类型数组名[纬数][纬数]...;数据类型可以是基础数据类型,也可以是其他复合数据类型。例如定义一个int型的一维数组,相关C语言代码可以如下写:

inta[3];这样就定义了一个可以存放3个int元素的数组a。使用a[0]可以访问第一个元素,a[2]可以访问第三个元素。

应该注意的是,a[3]已经不属于数组a了,使用a[3]可能会带来比较严重的错误。

使用a[3]是初学者常常会跳进的“陷阱”。

初学者看到a[3]不可用时,常常会感到迷惑,明明是inta[3];呀!为什么还说a[3]不可用呢?应该明白,即使是相同的符号,编译器也有可能根据C语言程序的上下文将其解释为不同的含义的,例如:

intb=3;intc=-b;intd=c-b;上面这几行C语言代码中,编译器会将“-”号分别解释为“负号”和“减号”。类似的,定义数组时的inta[3];中的“a[3]”和之后访问数组的“a[3]”具有不同的含义。前者表示数组a中共有3个元素,而C语言中的数组是从0开始计数的,因此之后只应使用a[0]、a[1]、a[2]这三个元素,a[3]已经是第4个元素了,是不应该使用的。

上例中,如果非要使用a[3],C语言程序也不一定会出错,而且你甚至可以使用a[4]、a[5]。但是不出错不代表没有错,具体原因我之前的文章里讨论过。

初始化数组的方法

在定义数组时,可以赋给其初值,例如:

inta[3]={1,2,3};上面这段C语言代码不仅定义了一个数组,而且还赋了初值{1,2,3},它相当于下面这几句:

inta[3];a[0]=1;a[1]=2;a[2]=3;可以看出,定义时赋初值可以少写一些C语言代码,更方便些。不过应该小心一个“陷阱”——给数组赋初值只能在定义的时候进行,已经定义好的数组,只能逐元素赋值。所以下面这段C语言代码是非法的:

inta[3];a[3]={1,2,3};//非法a={1,2,3};//非法其实原因也很简单,在数组被定义好之后,a[3]就表示第4个元素了,自然无法再存放{1,2,3}。

而数组名a在某种程度上相当于一个地址,自然也是无法存放{1,2,3}的。同样的道理,下面这样的操作也是不合法的:

inta[3]={1,2,3};intb[3];b[3]=a[3];//非法b=a;//非法定义一维数组时,可以不指定它的元素个数,例如下面这句C语言代码:

inta[]={1,2,3};这种情况下,程序员必须为数组指定初值,因为编译器要根据初值确定数组的元素个数。

例如上面这个例子,根据{1,2,3},编译器会认为数组a有3个元素。

初始化数组的一些技巧

有时候,在定义完数组之后,需要将其清零。按照上面的介绍,C语言代码可以如下写:

inta[3]={0,0,0};这样的确可以实现需求,但是如果数组的元素个数很多,再这么写就非常麻烦了。此时可以借助memset()函数将数组中所有元素归零:

inta[];memset(a,0,sizeof(int)*sizeof(a));不过,如果每定义一个数组,就需要写一次memset()还是有些麻烦。更方便的做法如下,请看相关C语言代码:

inta[]={0};虽然看起来上面这行C语言代码只对数组a的其中一个元素赋值,但是编译器确实会将其他元素也归零,感兴趣的读者可以自己写代码试一试。应注意,这里也有一个小“陷阱”——有些C语言初学者希望定义一个数组,并且将其所有元素赋值为1,于是写出下面这样的代码:

inta[]={1};

数组a中的元素自然不会与预期一致,编译器会将其他省略掉的元素归零,所以上面这句C语言代码执行之后,只有a[0]等于1,其他元素都为0。

在C语言程序开发中,有时候可能会希望将a中的某些元素赋初值,例如:

inta[];a[]=99;a[]=99;a[]=99;a[]=11;似乎只能这么写,没有办法在定义时赋初值。以前的确如此,但是现在很多C语言编译器支持下面这种写法:

inta[]={[...]=99,[]=11};

这与上面那几行逐元素赋初值的C语言代码是等价的,编译这段C语言代码,得到如下输出:

#gcct.c#./a.out小结

本节主要介绍了C语言中数组相关的一些“陷阱”与使用“技巧”。需要再说明的是,本节讨论的一些“技巧”其实是gcc的扩展,这对代码的可移植性有些损害。因此,其中的取舍需要由读者自己把握。

1
查看完整版本: C语言陷阱与技巧第14节,数组操作的一些