简而言之问题
我最近发现了gcc的扩展,我发现它非常酷,很有帮助。这允许您指定初始化元素在数组中的索引。而不是
static const uint8_t array[4] = {
2,
1,
3,
4
};
可以写
static const uint8_t array[4] = {
[1] = 1,
[0] = 2,
[2] = 3,
[3] = 4
};
但是,我有一个数组,我有一个或两个特定的值需要不同,数组的其余部分设置为某个默认值。我希望能够在初始化器中完成所有这些操作;
之类的东西static const uint8_t array[4] = {
[1] = 1,
[everything else] = 0
};
有谁知道这样做的好方法?我想出的唯一方法(看起来不仅仅是一点点hacky)是定义一个EVERYTHING_ELSE
宏,它取决于相同的值和数组长度 - 如下所示:
#define VALUE (8)
#define DEFAULT (1)
#define INDEX (2)
#define ARRAY_LENGTH (4)
#define EVERYTHING_ELSE(n, index, len) (((index) + (n)) % (len))
static const uint8_t array[ARRAY_LENGTH] = {
[EVERYTHING_ELSE(1, INDEX, ARRAY_LENGTH)] = DEFAULT,
[EVERYTHING_ELSE(2, INDEX, ARRAY_LENGTH)] = DEFAULT,
[EVERYTHING_ELSE(3, INDEX, ARRAY_LENGTH)] = DEFAULT,
[INDEX] = VALUE;
};
有点背景
我进行嵌入式系统编程,这通常意味着配置外围设备。在这种特定情况下,阵列的每个元素可能对应于外围设备中的通道。如果我正在为不同的电路板构建一个项目,引脚分配略有不同,我可能会在不同情况下使用不同的通道。为了帮助实现正确性和可移植性,我更喜欢在一个地方定义这个值,并编写依赖于这个值的代码。
此外,我需要确保停用该特定外设中的所有其他通道。在上面的例子中,我有一个简单的int数组,但通常情况更复杂(它是一个初始化器结构数组,或类似的东西)。我知道默认情况下静态数组将被初始化为零,但并不总是零对应于未初始化的情况;此外,我认为依赖于库常量是正确运行代码的特定值是不好的形式。
我可以使数组非const并在运行时进行初始化,但在嵌入式系统中,这可能是个问题。如果你只有6k的RAM,那么就有很强的动力将所有可以在编译时确定的内容放在闪存中,为实际需要在运行时改变的东西留出最大的RAM空间。
答案 0 :(得分:3)
这不是gcc专业,而是自C99以来的标准功能,称为designated initializer。结构字段也是可能的(这与强调imo更相关)。
请注意,标准仅允许指定单个索引(使用常量表达式),而不是范围,即gcc扩展名。也没有标准方法将“所有其他”字段设置为0以外的值(浮点数/复数为0.0,指针为NULL)。
根据标准的定义,未显式初始化的字段/元素设置为0.但是,如果您有一个较大的数组,其中很少的字段设置为非0,您应该从代码中显式设置这些字段(如果对象当然不是const
。原因是0初始化的全局对象不消耗ROM / Flash /文件空间,而非零初始化对象的初始化器必须完全存储。对于嵌入式系统,这显然不是一个好主意。
如果你必须设置一个大型数组,最好通过一个小程序用数组创建一个C源代码文件(我使用Python就是这样,因为这非常简单)。然后,此文件可以是程序代码中的#include
(如果static
),或者使用您的pregram编译/链接为任何其他源代码。