Поэлементный переход от меньшего массива к большему массиву - PullRequest
0 голосов
/ 03 февраля 2020

Я программирую ESP32 в платформе Arduino. Для моего приложения мне нужно создать буфер, в котором будет храниться информация как из настоящего, так и из последнего обращения к нему. Вот то, что я пытаюсь сделать.

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

Насколько я понимаю, это копирует buffer1, начиная с позиции индекса 0 в буфер2, начиная с позиции индекса 0, для 4 байтов (где 1 символ = 1 байт).

Информатика не является моим задним фоном, поэтому, возможно, есть какое-то фундаментальное решение или стратегия, которую я упускаю. Любые указатели будут оценены.

Ответы [ 2 ]

0 голосов
/ 03 февраля 2020

Правильный способ сделать это - использовать указатели буфера, , а не , делая резервные копии в бумажном виде. Делать бумажные копии с помощью memcpy особенно плохо на медленных устаревших микроконтроллерах, таких как AVR. Не совсем уверен, что MCU этот ESP32 получил, кажется, какой-то странный из Tensilica. В любом случае, этот ответ применим повсеместно для любого процессора, в котором у вас больше данных, чем длина слова данных процессора.

возможно, есть какое-то фундаментальное решение или стратегия, которые мне не хватает.

Действительно - действительно звучит так, что вы ищете кольцевой буфер . То есть массив фиксированного размера, который имеет указатель на начало допустимых данных и другой указатель на конец данных. Вы перемещаете указатели, а не данные. Это намного более эффективно как с точки зрения скорости выполнения, так и с точки зрения использования оперативной памяти, по сравнению с созданием наивных копий с memcpy.

0 голосов
/ 03 февраля 2020

У вас есть несколько вариантов реализации 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]. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 10 10 * 1042 *1043* 1042 * *1043* 1042

*1043* Solution 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 оставлено для вас как упражнение. ; -)

...