C语言陷阱与技巧第14节,数组操作的一些技巧,怎么只给一部分数组元素赋值?

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

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

数组的定义和使用

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

<数据类型> 数组名[纬数][纬数]...;

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

int a[3];

这样就定义了一个可以存放 3 个 int 元素的数组 a。使用 a[0] 可以访问第一个元素,a[2] 可以访问第三个元素。应该注意的是,a[3] 已经不属于数组 a 了,使用 a[3] 可能会带来比较严重的错误。

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

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

int b = 3;
int c = -b;
int d = c - b;

上面这几行C语言代码中,编译器会将“-”号分别解释为“负号”和“减号”。类似的,定义数组时的 int a[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]。但是不出错不代表没有错,具体原因我之前的文章里讨论过。

初始化数组的方法

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

int a[3] = {1, 2, 3};

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

int a[3];
a[0] = 1;
a[1] = 2;
a[2] = 3;

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

int a[3];
a[3] = {1, 2, 3};   // 非法
a = {1, 2, 3};  // 非法

其实原因也很简单,在数组被定义好之后,a[3] 就表示第 4 个元素了,自然无法再存放 {1, 2, 3}。而数组名 a 在某种程度上相当于一个地址,自然也是无法存放 {1, 2, 3}的。同样的道理,下面这样的操作也是不合法的:

int a[3] = {1, 2, 3};
int b[3];
b[3] = a[3]; // 非法
b = a;  // 非法

定义一维数组时,可以不指定它的元素个数,例如下面这句C语言代码:

int a[] = {1, 2, 3};

这种情况下,程序员必须为数组指定初值,因为编译器要根据初值确定数组的元素个数。

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

初始化数组的一些技巧

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

int a[3] = {0, 0, 0};

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

int a[1024];
memset(a, 0, sizeof(int)*sizeof(a));

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

int a[1024] = {0};

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

int a[1024] = {1};

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

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

int a[1024];
a[100] = 99;
a[101] = 99;
a[102] = 99;
a[200] = 11;

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

int a[1024] = { 
    [100 ... 102] = 99, 
    [200]=11 
};


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

# gcc t.c
# ./a.out 
99 99 99 11

小结

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

阅读更多:   C语言
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif