【发布时间】:2015-07-12 18:46:35
【问题描述】:
问题简述
我最近发现了一个 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;
};
一点背景
我从事嵌入式系统编程,这通常意味着配置外围设备。在这种特殊情况下,数组的每个元素可能对应于外围设备中的一个通道。如果我正在为不同的电路板构建一个项目,引脚分配略有不同,我可能会在不同的情况下使用不同的通道。为了帮助加强正确性和可移植性,我更喜欢在一个地方定义这个值,并编写依赖于这个值的代码。
此外,我需要确保该特定外围设备中的所有其他通道都已停用。在上面的示例中,我有一个简单的整数数组,但通常情况更复杂(它是一个初始化结构数组,或类似的东西)。我知道默认情况下静态数组将初始化为零,但零对应于未初始化的情况并不总是如此;此外,我认为将库常量作为正确运行代码的特定值是一种不好的形式。
我可以使数组非常量并在运行时进行初始化,但在嵌入式系统中这可能是个问题。如果您只有 6k 的 RAM,那么有强烈的动机将所有可以在编译时确定的内容放入闪存中,以便为实际需要在运行时改变的内容留出最大的 RAM 空间。
【问题讨论】:
-
好吧,如果您希望除少数几个值之外的所有值都初始化为零,那么为什么不将其初始化为零,然后在一些初始化例程中将少数特定值设置为应有的值?
-
零初始化“其他一切”很简单:
int a[5] = {[2]=5};和其余元素(第三个元素除外)被隐式设置为 0。但是要使用不同的值进行初始化,您必须使用一些技巧像你一样。 -
您可以使用“另一个”GNU 扩展:
uint8_t array[4] = { [0 ... 3] = DEFAULT, [1] = 1 };。 -
@cremno 实际上 OP 是标准 C 的一部分。只有您建议的范围初始化程序是 gcc 扩展。考虑到他似乎对扩展没问题,你的建议可能就是他想要的。
-
@JoachimPileborg 我不想这样做,因为这会迫使数组进入 RAM,在我的用例中这是不可接受的(请参阅最后的文字墙)