GCC数组默认填充值

时间:2015-07-12 18:46:35

标签: c arrays gcc embedded

简而言之问题

我最近发现了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空间。

1 个答案:

答案 0 :(得分:3)

这不是gcc专业,而是自C99以来的标准功能,称为designated initializer。结构字段也是可能的(这与强调imo更相关)。

请注意,标准仅允许指定单个索引(使用常量表达式),而不是范围,即gcc扩展名。也没有标准方法将“所有其他”字段设置为0以外的值(浮点数/复数为0.0,指针为NULL)。

根据标准的定义,未显式初始化的字段/元素设置为0.但是,如果您有一个较大的数组,其中很少的字段设置为非0,您应该从代码中显式设置这些字段(如果对象当然不是const。原因是0初始化的全局对象不消耗ROM / Flash /文件空间,而非零初始化对象的初始化器必须完全存储。对于嵌入式系统,这显然不是一个好主意。

如果你必须设置一个大型数组,最好通过一个小程序用数组创建一个C源代码文件(我使用Python就是这样,因为这非常简单)。然后,此文件可以是程序代码中的#include(如果static),或者使用您的pregram编译/链接为任何其他源代码。