【发布时间】:2018-06-05 06:50:05
【问题描述】:
我有一个这样定义的结构:
typedef struct {
sn74lvc138a_options_t decoder_opts;
uint32_t pin_int;
uint32_t pin_rst;
uint32_t pin_pwr;
...
} w5500_options_t;
嵌套结构 sn74lvc138a_options_t 结构如下所示:
static const sn74lvc138a_options_t sn74lvc138a_opts ={
.decoder_a = DECODER_A_GPIO,
.decoder_b = DECODER_B_GPIO,
.decoder_c = DECODER_C_GPIO,
.decoder_sel = DECODER_SEL_GPIO
};
这两个存储在两个不同的 C 模块中。 C 模块之一(也包含 w5500_options_t 实例的模块)定义了以下函数:
static const sn74lvc138a_options_t* _get_spi_decoder(void) {
return cpu_samv71_get_sn74lvc138a(); // This is a function from the other C module
}
我希望能够为编译时初始化执行以下操作:
static const w5500_options_t w5500_opts = {
.pin_int = SOMEVALUE1,
.pin_rst = SOMEVALUE2,
.pin_pwr = SOMEVALUE3,
.decoder_opts = _get_spi_decoder()
};
基本上我想要做的是在初始化块中获取对结构实例的引用。由于引用本身被定义为 const 并且函数返回一个 const 指针,编译器应该能够做到这一点(我使用的是 GCC 和 C99)。
现在的问题是:这是根本不允许的,还是我做错了什么而不允许这样做。我从编译器得到的确切错误消息是“初始化元素不是常量”。
【问题讨论】:
-
您不能为文件范围或静态变量初始化调用函数。 C++ 允许; C 没有。
-
请注意,通常不应创建以下划线开头的函数、变量或宏名称。 C11 §7.1.3 Reserved identifiers (部分)说: — 所有以下划线开头的标识符以及大写字母或另一个下划线始终保留供任何使用。 — 所有以下划线开头的标识符在普通名称空间和标记名称空间中始终保留用作具有文件范围的标识符。 另请参阅What does double underscore (
__const) mean in C? -
@JonathanLeffler:该函数被定义为静态并且具有文件范围。在这种情况下使用下划线是错误的吗?不太清楚“普通和标签空间”是什么意思。感谢您对静态变量初始化的关注。
-
这是一个函数。什么样的功能并不重要。它不能用作静态变量的初始化器。
-
下划线开头你是如履薄冰。很多人都这样做。许多人侥幸逃脱。标准并没有说你不能这样做,但你不应该这样做。如果你这样做了,你在未来的任何时候都有失败的风险,而且没有办法,只能改变代码,这样它就不会忽视标准给出的建议。
标签: c initialization constants