C语言数组被赋值之后,C语言陷阱与技巧第14节,数组操作的一些小窍门,怎样只给一部分数组元素赋值?...

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

18a72d2fcb6a2b08a97adf66e52956a0.png

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

数组的定义和使用

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

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

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

baa2fce1824c9310f7787f6fb3d792bf.png

应该注意的是,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]。但是不出错不代表没有错,具体原因我之前的文章里讨论过。

1ab992757e5fa30b1ceb1320a11add2f.png

初始化数组的方法

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

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}。

d924caf7ab07491f8e156bcb95c6a064.png

而数组名 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 个元素。

6122e77f80ceb441bac1e9a73df85683.png

初始化数组的一些技巧

有时候,在定义完数组之后,需要将其清零。按照上面的介绍,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};

bad35bd4d295b64fd72b93ca29b0973d.png

数组 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};

9d9b856d42a4d8015e77fdde2c3ada4d.png

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

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

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

举报/反馈

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值