C 使用函数中的常量指针进行编译时初始化
我有一个定义如下的结构:C 使用函数中的常量指针进行编译时初始化,c,initialization,constants,C,Initialization,Constants,我有一个定义如下的结构: typedef struct { sn74lvc138a_options_t decoder_opts; uint32_t pin_int; uint32_t pin_rst; uint32_t pin_pwr; ... } w5500_options_t; static const sn74lvc138a_options_t sn74lvc138a_opts ={ .decoder_a = DECODER_A_GPIO
typedef struct {
sn74lvc138a_options_t decoder_opts;
uint32_t pin_int;
uint32_t pin_rst;
uint32_t pin_pwr;
...
} w5500_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
};
嵌套结构sn74lvc138a_options_t结构如下所示:
typedef struct {
sn74lvc138a_options_t decoder_opts;
uint32_t pin_int;
uint32_t pin_rst;
uint32_t pin_pwr;
...
} w5500_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一起使用)
现在的问题是:这是完全不允许的,还是我做错了什么,不允许这样做。我从编译器得到的确切错误消息是“初始值设定项元素不是常量”。这是不允许的,因为编译器非常有帮助地为您提供了确切的原因
将与初始化相对应的运行时操作看作是可执行文件中的一个
memcpy()
,并放入进程堆中的某个地方;这就是你得到的一切。如果将一组位设置为预定义模式,则不会调用任何函数。不能为文件范围或静态变量初始化调用函数。C++允许;请注意,通常不应创建以下划线开头的函数、变量或宏名称。表示(部分):-所有以下划线和大写字母或另一个下划线开头的标识符始终保留供任何使用。-所有以下划线开头的标识符始终保留为在普通和标记名称空间中用作具有文件范围的标识符。另请参见@JonathanLeffler:该函数定义为静态函数,具有文件作用域。在这种情况下使用下划线是错误的吗?不太清楚“普通和标记空间”是什么意思。感谢您对静态变量初始化的介绍。这是一个函数。什么样的功能无关紧要;它不能用作静态变量的初始值设定项。您正在使用前导下划线如履薄冰。很多人都这样做。许多人侥幸逃脱了惩罚。标准没有说你不能做,但你不应该做。如果你这样做了,你在未来的任何时候都有失败的风险,我只希望,由于该路径中的所有元素都声明为const,编译器有一种直接的方法,只将该结构存储在ROM空间中,而不是同时存储在ROM和RAM中。感谢您提供的信息。我猜一个足够高级的编译器[*]可以解决这个问题,但是由于编写的代码无效(有一个函数调用,其中应该有编译时常量数据),所以实现它不是一个非常直观的优化。