C++ 从较小阵列向较大阵列的元素方向移动
我正在Arduino框架中编程一个ESP32。对于我的应用程序,我需要创建一个缓冲区来存储当前和上次访问时的信息。以下是我试图做的C++ 从较小阵列向较大阵列的元素方向移动,c++,arduino,embedded,arduino-c++,C++,Arduino,Embedded,Arduino C++,我正在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 m
//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}
从我通过在线搜索了解到的情况来看,我正在尝试实现的“saveold”功能
应该为这些数组操作实现某种形式的memmove
我试图将其拼凑在一起,但我总是覆盖buffer2的值,而不是在保留旧值的同时以某种方式移入新值
这就是我的全部:
void saveold() {
memmove(&buffer2[0], &buffer1[0], (sizeof(buffer1[0]) * 4));
}
据我所知,这会将从索引位置0开始的buffer1复制到从索引位置0开始的buffer2,共复制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)
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];
}
}
void saveold(){
//将下半部分“移位”到上半部分,保存最近的值
size_t size=sizeof buffer2/sizeof buffer2[0];
对于(int i=0;i
将此知识应用于解决方案2的操作留给您。;-) 正确的方法是使用缓冲区指针,而不是通过硬拷贝备份。使用memcpy进行硬拷贝在速度较慢的传统微控制器(如AVR)上尤其糟糕。不太清楚这台ESP32的MCU是什么,似乎是来自Tensilica的奇怪的一台。不管怎么说,这个答案普遍适用于任何数据超过CPU数据字长的处理器 也许有一些根本性的解决方案或策略是我所缺少的
的确,听起来你要找的是一个环形缓冲区。也就是说,一个大小固定的数组,其中一个指针指向有效数据的开头,另一个指针位于数据的结尾。您移动的是指针,而不是数据。与使用
memcpy
制作简单的硬拷贝相比,这在执行速度和RAM使用方面都要高效得多,因为您实际上没有移动任何东西。您每次只是从buffer1
复制到buffer2
中的同一位置。我个人不会费心移动实际数据,而是保留一个标志,告诉您每次调用时开始复制到哪个字节。但如果您真的必须复制,请执行以下操作:memmove(&buffer2[4],&buffer2[0],(sizeof(buffer2[0])*4));memcpy(&buffer2[0],&buffer1[0],(sizeof(buffer1[0])*4))代码>选择C或C++,而不是两者。最好的答案取决于语言。在微控制器上使用memcpy几乎从来都不是正确的解决方案。在95%的情况下,人们在这样的系统中使用memcpy,他们应该使用指针交换。尽管在这种特定情况下,最好的解决方案似乎是保留一个单环缓冲区-假设没有硬件限制,例如DMA强制执行双缓冲区设计,这在问题中没有任何说明。@Lundin如果您需要性能和足够的RAM,那就对了。另一种方法是memcpy()
。正如我所写的,还有更多的可能性,这完全取决于需求和环境。我刚刚从他所在的地方找到了OP。OP的代码已经有了多个缓冲区,所以只要做最小的更改,正确的解决方案就是进行指针交换。老实说,解决方案1的简单性非常吸引人。它对我的应用程序也很有效,所以我将坚持使用它。不过,为了便于学习,我还将尝试实现一个环形缓冲区(现在我知道它叫什么了)。这很有教育意义!