Хранение элемента в массиве это указатель - PullRequest
0 голосов
/ 24 февраля 2020

Я бы хотел сохранить элемент в массиве, так как данный массив параметров является указателем на реальный массив (для предотвращения ненужного копирования данных).

bool storeElementToArray(sensor element, sensor *sensors) {
  for (int i = 0; i < (sizeof(sensors) / sizeof(element) - 1); i++) {
    if (!sensors[i].getIsObject()) { // Check if the current element is already a "real" sensor or just a reserved part of memory to store a a sensor
      helper::debug(F("Stored at index "), false ,false);
      helper::debugInt(i, true, false);
      sensors[i] = element;
      break;
    }
  }
}

sensor sensors[5];

Я хочу сохранить от element до sensors, тогда как sensors должен быть только указателем / ссылкой на массив sensors[5], потому что мне нужно указать, в каком массиве должен храниться элемент , Как мне этого добиться?

1 Ответ

1 голос
/ 24 февраля 2020

«Указатель / ссылка» на массив, кажется, указывает на некоторые проблемы в понимании того, как работают указатели по отношению к массивам.

Когда вы берете указатель на элемент массива и «передаете массив» для такой функции вы запускаете затухание массива в указатель, и в итоге вы передаете указатель на первый элемент.

#include <iostream>

void f(int* p) {
    std::cout << p << '\n';
}

int main() {
    int arr[5];

    // both are exactly the same
    f(arr); 
    f(&arr[0]);
}

Таким образом, в вашем случае, передача sensors через sensor* будет работать, и вы сможете изменить содержимое массива:

#include <iostream>
#include <algorithm>

void set(int val, int ix, int* storage) {
    storage[ix] = val;
}

int main() {
    int values[10];
    std::fill(std::begin(values), std::end(values), 0);

    set(42, 3, values);

    for (auto v : values) {
        std::cout << v << '\n';
    }
}

При этом, если вы передаете массив, вам нужно каким-то образом оценить размер, чтобы избежать заграничный доступ; Один из способов сделать это - передать его в качестве другого параметра.

При этом гораздо предпочтительнее использовать std::array, который затем можно передать в качестве ссылки. Таким образом, вы избегаете всех указателей и получаете размер, передаваемый автоматически. Недостатком является то, что вам нужно знать размер во время компиляции.

К сожалению, при предоставлении std::string_view в C ++ отсутствует встроенный примитив для просмотра памяти. std::vector используется в настольном коде, но его использование во встроенной программе для ограниченного MCU довольно сомнительно. В этом случае вам может понадобиться / вы хотите написать собственный тип, включающий указатель и размер, например:

template<typename T>
struct ArrayView {
    T* ptr;
    std::size_t sz;
public:
    template<int arrSize>
    ArrayView(T (&arr)[arrSize]) : ptr(arr), sz(arrSize) { }

    T& operator[](int i) { return ptr[i]; }
    std::size_t size() const { return sz; }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...