Linux GNU C结构体数组初始化示例

实然心血来潮,想学习一下结构体数组的初始化方面的知识。GCC特有的数组初始化的风格:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 数组赋值另一种方式,但只在gcc下编译通过,g++不能
enum {
AAA = 0,
BBB,
CCC,
DDD,
};
// 只对感兴趣的索引值进行赋值,而不管下标的顺序
static const int regs[] = {
[DDD] = 250,
[CCC] = 3,
[AAA] = 180,
};

这种风格在kernel代码中经常看到。它不按照数组下标顺序,而是使用自定义的“索引”来赋值,比如Intel网卡igb驱动中一处代码:

1
2
3
static const struct e1000_info *igb_info_tbl[] = {
[board_82575] = &e1000_82575_info,
};

从代码中可以清晰知道,这个结构体是针对82575的——board_82575比数字0更直观易读。
但是使用g++却无法编译,编译错误提示如下:

1
sorry, unimplemented: non-trivial designated initializers not supported

下面再看看结构体数组的初始化,先给出结构体的定义:

1
2
3
4
5
6
7
8
9
10
11
12
enum control_type
{
TYPE_GPIO = 0,
TYPE_IIC = 1,
TYPE_SPI = 2,
};

typedef struct control_info_t {
const char *name;
enum control_type type;
int enable;
}control_info;

初始化方式一,依次给数组内元素赋值,如下::

1
2
3
4
5
6
control_info control_info1[3] = 
{
{"FOO_GPIO", TYPE_GPIO, 1},
{"FOO_IIC", TYPE_IIC, 0},
{"FOO_SPI", TYPE_SPI, 1},
};

方式二,先声明再赋值,如下:

1
2
3
4
control_info control_info[3];
control_info[TYPE_SPI].name = "FOO_SPI";
control_info[TYPE_SPI].type = TYPE_SPI;
control_info[TYPE_SPI].enable = 1;

方式三,不按照顺序,只对感兴趣几项赋值,如下:

1
2
3
4
5
control_info control_info2[3] = 
{
[TYPE_SPI] = {"FOO_SPI", TYPE_SPI, 1},
[TYPE_GPIO] = {"FOO_GPIO", TYPE_GPIO, 1},
};

从这个方式上看,类型为SPI的“索引值”对应即为SPI,但无须理会类型SPI的具体值。 本文完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
结果:
struct test
250 0 180 3
111 name: FOO_IIC type: 1 enable: 0
222 name: FOO_GPIO type: 0 enable: 1
333 name: FOO_SPI type: 2 enable: 1
*/

#include <stdio.h>
#include <inttypes.h>

///////////////////////
// 简单int类型的数组
// 数组赋值另一种方式,但只在gcc下编译通过,g++不能
enum {
AAA = 0,
BBB,
CCC,
DDD,
};
// 只对感兴趣的索引值进行赋值,而不管下标的顺序
static const int regs[] = {
[DDD] = 250,
[CCC] = 3,
[AAA] = 180,
};

void struct_test1()
{
printf("%d %d %d %d\n", regs[DDD], regs[BBB], regs[AAA], regs[CCC]);
}

///////////////////////
// 结构体数组初始化示例
enum control_type
{
TYPE_GPIO = 0,
TYPE_IIC = 1,
TYPE_SPI = 2,
};

typedef struct control_info_t {
const char *name;
enum control_type type;
int enable;
}control_info;

void struct_test_2()
{
// c++风格,用g++并使用 -std=c++11
//control_info gcontrol_info0 {.name = "FOO", .type = TYPE_SPI, .enable=1};

// 三个依次赋值
control_info control_info1[3] =
{
{"FOO_GPIO", TYPE_GPIO, 1},
{"FOO_IIC", TYPE_IIC, 0},
{"FOO_SPI", TYPE_SPI, 1},
};
printf("111 name: %s type: %d enable: %d\n", control_info1[TYPE_IIC].name, control_info1[TYPE_IIC].type, control_info1[TYPE_IIC].enable);

// GNU风格赋值
control_info control_info2[3] =
{
[TYPE_SPI] = {"FOO_SPI", TYPE_SPI, 1},
[TYPE_GPIO] = {"FOO_GPIO", TYPE_GPIO, 1},
};
printf("222 name: %s type: %d enable: %d\n", control_info2[TYPE_GPIO].name, control_info2[TYPE_GPIO].type, control_info2[TYPE_GPIO].enable);


// 只有一个赋值
control_info control_info[3];
control_info[TYPE_SPI].name = "FOO_SPI";
control_info[TYPE_SPI].type = TYPE_SPI;
control_info[TYPE_SPI].enable = 1;

printf("333 name: %s type: %d enable: %d\n", control_info[TYPE_SPI].name, control_info[TYPE_SPI].type, control_info[TYPE_SPI].enable);
}

int main(void)
{
printf("struct test\n");

struct_test1();
struct_test_2();

return 0;
}

李迟 2016.10.13 周四 中午午休前