刚开始使用微控制器进行C ++编程,我遇到了以下情况*:在始终保证具有固定值的结构上具有非静态const字段会很方便(对于每个实例,相同坚固)。
给定一个结构
struct S {
const uint8_t c; // Should always be 42
char v;
uint32_t arr[4];
}
Run Code Online (Sandbox Code Playgroud)
我想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;
}
Run Code Online (Sandbox Code Playgroud)
*有关为什么要执行此操作的上下文:这看起来似乎很奇怪,因为如果值始终相同,为什么还要麻烦存储它呢?很好地想象,所讨论的结构是一个位域,对应于微控制器与之通信的IC的寄存器。这些寄存器有时具有“保留”字段,并且数据表指定必须在这些字段中写入的值。从程序员的角度来看,如果我不必手动处理这些位,那将很方便。
C ++ 11为您提供std::array了一个原始数组,但没有任何“负数”(数组衰减,无法复制)。使用它,您可以获得想要的东西
struct S {
const uint8_t c = 42;
char v = 'a';
std::array<uint32_t, 4> arr{};
// This allows using "S s1;"
S() {}
S(uint32_t v, std::array<uint32_t, 4> arr) : v(v), arr{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
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;
}
Run Code Online (Sandbox Code Playgroud)
哪个输出
s1.c = 42
s1.v = 'a'
s1.arr[3] = 0
s2.c = 42
s2.v = 'v'
s2.arr[3] = 3
Run Code Online (Sandbox Code Playgroud)
如果绝对要在其中包含原始数组,S则另一种选择是std::initializer_list在构造函数中使用a 。看起来像
struct S {
const uint8_t c = 42;
char v = 'a';
uint32_t arr[4]{};
// This allows using "S s1;"
S() {}
S(uint32_t v, std::initializer_list<uint32_t> data) : v(v)
{
int i = 0;
for (auto e : data)
arr[i++] = e;
}
};
// 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
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;
}
Run Code Online (Sandbox Code Playgroud)
而且,您获得的结果与使用的代码相同std::array。
| 归档时间: |
|
| 查看次数: |
57 次 |
| 最近记录: |