嵌入式Hacker (es-hacker)

Embedded bsp developer enjoys thinking and hacking opensource and develop boards(NanoPi, LicheePi, RPi...)

0%

每天一点C / 一维数组的初始化

哈喽,继续记录我的学习心得。

每天一点系列是我对微习惯的践行。现在能做到每天一点 C,将来就会有更多的每天一点系列,没人规定嵌入式软件工程师就只能学习 C 语言和折腾 Linux,不要给自己设限。

为什么是每天一点?
养成写作习惯的第一步:放弃追求大段的、固定的、安静的写作时间,培养随时写作的能力。

同样的技巧也能应用到技术学习上,工程师也可以放弃追求大段的、固定的、安静的看书写代码的时间。遇到一个新知识,第一时间找到相关资料,找到切入点并将其记录在自己的技术笔记中,并且定期复查及完善。

30 岁的中年工程师能做到每天坚持学习,你还抱怨没时间学习吗?


每天一点C / 一维数组的初始化

正文目录:

1
1. 用以逗号分隔的值列表来初始化数组
2
2. 把数组设置为只读
3
3. 忘记初始化数组
4
4. 部分初始化数组
5
5. 让编译器自动推导数组大小
6
6. 指定初始化器 (designated initializer )

运行环境:

  • Ubuntu 16.04
  • gcc version 5.4.0

1. 用以逗号分隔的值列表来初始化数组

演示 demo:

1
#include <stdio.h>
2
#define MONTHS 12
3
int main(void)
4
{
5
    int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};
6
    int index;
7
    
8
    for (index = 0; index < MONTHS; index++)
9
        printf("Month %d has %2d days.\n", index +1, days[index]);
10
    
11
    return 0;
12
}

运行效果:

1
$ gcc day_mon1.c -o day_mon
2
$ ./day_mon 
3
Month 1 has 31 days.
4
Month 2 has 28 days.
5
...
6
Month 12 has 31 days.

相关要点:

  • MONTHS 是符号常量,使用符号常量表示数组大小,是推荐做法

2. 把数组设置为只读

要创建只读数组,可以用 const。

演示 demo:

1
#define MONTHS 12
2
int main(void)
3
{
4
    const int days[MONTHS] = {31,28,31,30,31,30,31,31,30,31,30,31};
5
    days[1] = 29; // ERROR
6
    return 0;
7
}

运行效果:

1
$ gcc const_array.c -o const_array
2
const_array.c: In function ‘main’:
3
const_array.c:6:13: error: assignment of read-only location ‘days[1]’
4
     days[1] = 29; // ERROR

3. 忘记初始化数组

演示 demo:

1
#define SIZE 4
2
int main(void)
3
{
4
    int no_data[SIZE];  /* uninitialized array */
5
    int i;
6
    
7
    printf("%2s%14s\n",
8
           "i", "no_data[i]");
9
    for (i = 0; i < SIZE; i++)
10
        printf("%2d%14d\n", i, no_data[i]);
11
    
12
    return 0;
13
}

运行效果:

1
$ gcc no_data.c -o no_data
2
$ ./no_data
3
 i    no_data[i]
4
 0       4195872
5
 1             0
6
 2       4195488
7
 3             0

相关要点:

  • 打印的是内存相应位置上的现有值。

  • 可以把数组创建成不同的存储类别 (storage class),例如auto / static。上述结论仅适用于 auto 变量,即在函数内部声明,且声明时未使用关键字 static 的变量。

4. 部分初始化数组

演示 demo:

1
#define SIZE 4
2
int main(void)
3
{
4
    int some_data[SIZE] = {1492, 1066};
5
    int i;
6
    
7
    printf("%2s%14s\n",
8
           "i", "some_data[i]");
9
    for (i = 0; i < SIZE; i++)
10
        printf("%2d%14d\n", i, some_data[i]);
11
    
12
    return 0;
13
}

运行效果:

1
$ gcc some_data.c -o some_data
2
$ ./some_data 
3
 i  some_data[i]
4
 0          1492
5
 1          1066
6
 2             0
7
 3             0

相关要点:

  • 如果部分初始化数组,剩余的元素会被编译器初始化为 0。

  • 如果初始化列表的项数多于数组元素个数,gcc 5.4 编译器只会警告有多余的元素:(warning: excess elements in array initializer)。

5. 让编译器自动推导数组大小

演示 demo:

1
int main(void)
2
{
3
    const int days[] = {31,28,31,30,31,30,31,31,30,31};
4
    int index;
5
    
6
    for (index = 0; index < sizeof days / sizeof days[0]; index++)
7
        printf("Month %2d has %d days.\n", index +1, days[index]);
8
9
    return 0;
10
}

运行效果:

1
$ gcc day_mon2.c -o day_mon2
2
$ ./day_mon2 
3
Month  1 has 31 days.
4
Month  2 has 28 days.
5
...
6
Month 10 has 31 days.

相关要点:

  • 初始化数组时省略方括号中的数字,编译器会根据初始化列表中的项数来确定数组的大小。

  • sizeof(array) / sizeof(array[0]) 常用于计算数组的长度。这种方式的弊端:无法察觉初始化列表中的项数有误,遗漏了 2 个月份。

6. 指定初始化器 ( designated initializer )

该特性用于初始化指定的数组元素,例如,只初始化数组中的最后一个元素。

演示 demo:

1
#define MONTHS 12
2
int main(void)
3
{
4
    int days[MONTHS] = {31,28, [4] = 31,30,31, [1] = 29};
5
    int i;
6
    
7
    for (i = 0; i < MONTHS; i++)
8
        printf("%2d  %d\n", i + 1, days[i]);
9
    
10
    return 0;
11
}

运行效果:

1
$ gcc designate.c -o designate
2
 1  31
3
 2  29
4
 3  0
5
 4  0
6
 5  31
7
 6  30
8
 7  31
9
 8  0
10
 9  0
11
10  0
12
11  0
13
12  0

相关要点:

  • 这是 C99 的特性。

  • 如果指定初始化器后面有更多的值,那么后面这些值将被用于初始化指定元素后面的元素:在days[4] 被初始化为 31,days[5] 被初始化为 30。

  • 如果再次初始化指定的元素,那么最后的初始化将会取代之前的初始化:days[1] 的最终值为 29。

  • 如果未指定元素大小,编译器会把数组的大小设置为足够装得下初始化的值:int staff[] = {1, [6] = 4, 9, 10},staff 的长度为 9。

思考技术,也要思考人生

学习技术,更要学习如何生活

你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。

如果你也对 嵌入式系统 (Linux、RTOS、OpenWrt、Android) 和 开源软件 感兴趣,并且想和更多人互相交流学习的话,请关注我的公众号:嵌入式Hacker,一起来学习吧。

无论是关注或转发,还是打赏,都是对作者莫大的支持。对了,记得点 在看和点赞 ,如果你还想看到我的推送的话。

ps:
欢迎加入我的微信群:加我微信,我拉你进群,暗号(加群)。

祝各位工作顺利,家庭幸福,财源滚滚~

这是一篇有趣的文章吗?

欢迎关注我的其它发布渠道