如果没有一些实践,C 声明可能很难理解。在下文中,我忽略了与指针有关的一些困难。网上有很多很好的参考资料,更详细地解释了 C 声明的工作原理。也就是说,这里有一个简化的版本,说明如何理解您提供的代码。
首先,你如何声明一个数组a 的N 某种类型的T 元素?在 C 中,这写为
T a[N];
注意T 是A 的元素类型。不管T 是什么,这都是真的。例如,
int a[N];
char a[N];
在每种情况下,数组元素的类型首先出现在声明中。这也适用于结构类型。即,
struct foo a[N];
声明N 元素的数组a,每个元素都是struct foo。在这种情况下,与前两个示例不同,在源文件或包含的标头之一中的某个位置之前必须有 struct foo 的定义。
因此,使用您示例中的类型,代码
struct SOutputQuantity { /* ... */ };
static struct SOutputQuantity _outputTypeToQuantityMap[N];
将_outputTypeToQuantityMap 声明为N 个SOutputQuantity 结构的数组。
非常正确,您会指出这与您展示的代码相同。您在这里遇到的最后一件事是 initializer 的概念。假设您要声明一个由 3 个整数组成的数组,并在编译时初始化该数组。语法是
int a[3] = { 1, 2, 3 };
编译器安排(不知何故,这并不重要)
a[0] == 1
a[1] == 2
a[2] == 3
在您的程序开始执行之前。接下来,当你有一个 arra 声明的初始化器时,你可以省略数组中元素的数量,因为编译器可以计算出来。所以,
int a[] = { 1, 2, 3 };
与之前的声明相同。
所以现在,你的示例代码的最后几行可以理解为
struct SOutputQuantity _outputTypeToQuantityMap[] = {
/* constant #1 */,
/* constant #2 */,
};
这段代码声明和初始化一个二元素数组。唯一需要理解的部分是{,} 的含义。这本身就相当令人困惑,它是 C 提供的一系列快捷方式的结果。让我们从没有数组开始(还有一个更简单的结构,所以我不必输入那么多)。
struct foo { int a; int b; };
struct foo x = { 1, 2 };
上面例子的第二行声明并初始化了一个struct foo类型的变量f,这样
x.a == 1
x.b == 2
C 允许您从初始化程序中省略尾随结构成员,用零填充省略的值。特别是,您可以省略 all 结构成员。
struct foo x = { 1 }; // x.a == 1; x.b == 0
struct foo x = { }; // x.a == 0; x.b == 0
最后,C 允许您在最后一个初始化程序之后包含一个尾随逗号:
struct foo x = { 1, 2, }; // x.a == 1; x.b == 2
struct foo x = { 1, }; // x.a == 1; x.b == 0
我不确定标准是否允许,但您的编译器似乎也允许
struct foo x = { , }; // x.a == 0; x.b == 0
所以,毕竟,
static struct SOutputQuantity _outputTypeToQuantityMap[] = {
{,},
{,},
};
声明一个包含 struct SOutputQuantity 类型的每个元素的 2 元素数组,并同时初始化该数组的每个元素,以便将 outputQuantity 和 valueType 字段初始化为零。