按元素从较小的数组转移到较大的数组

Element-wise shifting from smaller array to a larger array

我正在使用 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}

根据我通过在线搜索能够理解的内容,我正在尝试制作 "saveold" 功能 应该为这些数组操作实现某种形式的 memmove

我试图将它拼凑起来,但我总是覆盖 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 进行硬拷贝在 AVR 等慢速传统微控制器上尤其糟糕。不太确定这个 ESP32 有什么 MCU,似乎是来自 Tensilica 的一些古怪的。无论如何,这个答案普遍适用于任何数据超过 CPU 数据字长的处理器。

perhaps there is some fundamental solution or strategy that I am missing.

确实 - 听起来您正在寻找的确实是一个 环形缓冲区。也就是说,一个固定大小的数组,它有一个指向有效数据开头的指针,另一个指针指向数据的末尾。您移动指针,而不是数据。与使用 memcpy.

制作简单的硬拷贝相比,这在执行速度和 RAM 使用方面都更加高效