Warm tip: This article is reproduced from stackoverflow.com, please click
arduino arduino-c++ c++ embedded

Element-wise shifting from smaller array to a larger array

发布于 2020-04-13 09:53:59

I am programming an ESP32 in the Arduino framework. For my application, I need to create a buffer which will store information from both the present and the last time it was accessed. Here is what I am attempting to do.

//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}

From what I've been able to understand through searching online, the "saveold" function I'm trying to make should implement some form of memmove for these array operations

I've tried to piece it together, but I always overwrite the value of buffer2 instead of somehow shifting new values in, while retaining the old ones

This is all I've got:

void saveold() {
  memmove(&buffer2[0], &buffer1[0], (sizeof(buffer1[0]) * 4));
}

From my understanding, this copies buffer1 starting from index position 0 to buffer2, starting at index position 0, for 4 bytes (where 1 char = 1 byte).

Computer science is not my backround, so perhaps there is some fundamental solution or strategy that I am missing. Any pointers would be appreciated.

Questioner
kevinaguy
Viewed
68
the busybee 2020-02-03 15:28

You have multiple options to implement saveold():

Solution 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];
}

Solution 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]);
}

Some notes

  • There are even more ways to do it. Anyway, choose the one you understand best.
  • Be sure that buffer2 is exactly double size of buffer1.
  • memcpy() can be used safely if source and destination don't overlap. memmove() checks for overlaps and reacts accordingly.
  • &buffer1[0] is the same as buffer1 + 0. Feel free to use the expression you better understand.
  • sizeof is an operator, not a function. So sizeof buffer[0] evaluates to the size of buffer[0]. A common and most accepted expression to calculate the size of an array dimension is sizeof buffer1 / sizeof buffer1[0]. You only need parentheses if you evaluate the size of a data type, like sizeof (int).

Solution 3

The last note leads directly to this improvement of solution 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];
    }
}

To apply this knowledge to solution 2 is left as an exercise for you. ;-)