我在Arduino框架中编写ESP32。对于我的应用程序,我需要创建一个缓冲区,该缓冲区将存储当前和上次访问它的信息。这是我正在尝试做的事情。
//first buffer
char buffer1[4];
//second buffer
char buffer2[8];
void setup {
//setup
}
//buffer1 values will change with each iteration of loop from external inputs
//buffer2 must store most recent values of buffer1 plus values of buffer1 from when loop last ran
for example:
**loop first iteration**
void loop {
buffer1[0] = {1};
buffer1[1] = {2};
buffer1[2] = {3};
buffer1[3] = {1};
saveold(); //this is the function I'm trying to implement to save values to buffer2 in an element-wise way
}
//value of buffer2 should now be: buffer2 = {1,2,3,1,0,0,0,0}
**loop second iteration**
void loop {
buffer1[0] = {2};
buffer1[1] = {3};
buffer1[2] = {4};
buffer1[3] = {2};
saveold();
}
//value of buffer2 should now be: buffer2 = {2,3,4,2,1,2,3,1}
从我通过在线搜索所能了解的内容来看,我想创建的“保存”功能应该为这些数组操作实现某种形式的记忆
我尝试将其组合在一起,但是我总是覆盖buffer2的值,而不是以某种方式移入新值,同时保留旧值
这就是我所拥有的:
void saveold() {
memmove(&buffer2[0], &buffer1[0], (sizeof(buffer1[0]) * 4));
}
据我了解,这会将缓冲区1从索引位置0开始复制到缓冲区2,从索引位置0开始复制4个字节(其中1个字符= 1个字节)。
计算机科学不是我的背景,所以也许我缺少一些基本的解决方案或策略。任何指针将不胜感激。
您可以通过多种选择来实现saveold()
:
解决方案1
void saveold() {
// "shift" lower half into upper half, saving recent values (actually it's a copy)
buffer2[4] = buffer2[0];
buffer2[5] = buffer2[1];
buffer2[6] = buffer2[2];
buffer2[7] = buffer2[3];
// copy current values
buffer2[0] = buffer[0];
buffer2[1] = buffer[1];
buffer2[2] = buffer[2];
buffer2[3] = buffer[3];
}
解决方案2
void saveold() {
// "shift" lower half into upper half, saving recent values (actually it's a copy)
memcpy(buffer2 + 4, buffer2 + 0, 4 * sizeof buffer2[0]);
// copy current values
memcpy(buffer2 + 0, buffer1, 4 * sizeof buffer1[0]);
}
一些注意事项
buffer2
是的两倍大小buffer1
。memcpy()
如果源和目标不重叠,则可以安全使用。memmove()
检查重叠并做出相应的反应。&buffer1[0]
与相同buffer1 + 0
。随意使用您更好理解的表达方式。sizeof
是运算符,而不是函数。因此sizeof buffer[0]
计算为的大小buffer[0]
。用于计算数组维数大小的常见且最常用的表达式是sizeof buffer1 / sizeof buffer1[0]
。仅当评估数据类型的大小时才需要括号sizeof (int)
。解决方案3
最后的注释直接导致解决方案1的改进:
void saveold() {
// "shift" lower half into upper half, saving recent values
size_t size = sizeof buffer2 / sizeof buffer2[0];
for (int i = 0; i < size / 2; ++i) {
buffer2[size / 2 + i] = buffer2[i];
}
// copy current values
for (int i = 0; i < size / 2; ++i) {
buffer2[i] = buffer1[i];
}
}
将此知识应用到解决方案2的练习留给您。;-)
在微控制器上使用memcpy几乎永远不是正确的解决方案。在人们在此类系统中使用memcpy的情况中,大约有95%的情况下,他们应该使用指针交换。尽管在这种特定情况下,最好的解决方案似乎是保留单个环形缓冲区-假设不存在诸如DMA强制执行双缓冲区设计之类的硬件限制,问题中没有任何内容表明。
@Lundin如果您需要性能并具有足够的RAM,那是对的。另一种方法
memcpy()
是确定。如我所写,还有更多的可能性,而这完全取决于需求和环境。我刚拿起他所在的OP。OP的代码原样已经具有多个缓冲区,因此,只需进行最小的更改,正确的解决方案便是进行指针交换。
老实说,解决方案1的纯粹简单性很吸引人。它对于我的应用程序也非常有效,因此我会坚持下去。但是,出于学习目的,我还将尝试实现环形缓冲区(现在我知道它的含义)。这是教育性的!