【发布时间】:2020-02-15 12:29:16
【问题描述】:
最近刚开始为微控制器进行 C++ 编程,我遇到了一些情况*,在结构上使用非静态 const 字段会很方便,该结构始终保证具有固定值(对于每个sturct 的实例,永远)。
给定一个结构
struct S {
const uint8_t c; // Should always be 42
char v;
uint32_t arr[4];
}
我希望c 成为一个常量值,并且每次都使用相同的常量值。我希望能够使用大括号初始化列表的便利性来设置 v 和 arr 的成员,如
S some_var = {'v', { 0, 1, 2, 3 } };
因为我希望c 是一个常量,所以我的印象是我必须使用初始化列表来设置c,例如S() : c(42) {},它工作得很好,只要我不尝试也初始化arr,在这种情况下,我不知道列表应该是什么样子。这使用 C++11 可行吗? (如果这在 C++11 中不可行,但在一些较新的标准中,也对答案感兴趣。)
示例代码:
#include <stdio.h>
#include <stdint.h>
struct S {
const uint8_t c; // Should always be 42 on every instance
// of the struct due to hardware shenanigance
// (i.e. this struct is the representation of a register value)
char v;
uint32_t arr[4];
// This allows using "S s1;"
S() : c(42), v('a'), arr{} {}
// This allows using "S s2 = { 'v', 0, 1, 2, 3 };" works but it's clumsy:
S(uint32_t v, uint32_t arr0, uint32_t arr1, uint32_t arr2, uint32_t arr3) :
c(42), v(v), arr{ arr0, arr1, arr2, arr3 } {}
// I would like to do something along the lines of "S s2 = { 'v', { 0, 1, 2, 3 } };":
// S(uint32_t v, uint32_t arr[4] /*?*/) :
// c(42), v(v), arr{/*?*/} {}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
// Initialiation like this works with the line:12 signature:
S s2 = { 'v', 0, 1, 2, 3 };
// I'd like to initialize like this:
// S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
*关于我为什么要这样做的上下文:这似乎是一件奇怪的事情,因为如果值始终相同,为什么还要麻烦存储它呢?想象一下,所讨论的结构是一个位域,它对应于与微控制器通信的 IC 的寄存器。这些寄存器有时具有“保留”字段,数据表指定您必须在这些字段中写入的值。从程序员的角度来看,如果我不必手动设置这些位,那会很方便。
【问题讨论】:
-
如果所有实例都具有相同的值,听起来你需要一个静态变量。这不仅会节省空间,因为所有对象都将共享一个变量,它还允许您保持聚合初始化。
-
@NathanOliver 请阅读问题末尾的脚注。假设您想将位域传递给
1111000xxxxxxxxx形式的某些硬件,其中11110000始终相同/必需,xxxxxxxx是您要通信的数据。 -
注意:编译器可能会在
v和arr之间插入填充,这可能会扰乱与微控制器的通信。大多数编译器允许您避免填充(通过#pragma pack之类的东西),但这并不是真正可移植的。 -
是的,@MaxLanghof 是正确的,我需要该值实际存在于内存中。据我了解,静态 const 不能满足这一点。关于如何改写问题以便更清楚的任何提示?我知道填充问题,我只是想保持示例简单。