Почему я не могу получить размер массива указателей

ну, я пытаюсь получить размер массива для преобразования шестнадцатеричного значения в значение int. но если я попытаюсь получить размер массива, он будет возвращаться каждый раз 2. На самом деле.Я не понимаю. как получить размер массива, вы можете мне помочь?

это мой код

unsigned long w;

void setup() {
  Serial.begin(9600);

  uint8_t * packet = read_packet();
  Serial.println(sizeof(packet)); // PROMLEM IS HERE, IT RETURNS EVERYTIME "2"

  for (int i = 0; i < 4; i++)
  {
    Serial.println(packet[i]); //if i print the packet array all elements are here
  }

  /*
    for (byte i = 0; i < sizeof packet; i++) {
      w = w + ((long)(packet[sizeof packet - (i + 1)]) << (i * 8));
    }

  */
}

void loop() {
  // put your main code here, to run repeatedly:

}

uint8_t *read_packet() {
  static uint8_t buffer[4];

  buffer[0] = 0x00;
  buffer[1] = 0x32;
  buffer[2] = 0x32;
  buffer[3] = 0x32;

  Serial.println(sizeof buffer);
  return buffer;
}

если я распечатаю массив пакетов, все 4 элемента будут там 0,50,50,50. но размер массива возвращается каждый раз, когда "2". даже если я увеличу размер массива.

может быть, вы можете подумать, почему я использую указатели? из-за моего предыдущего ответа на вопрос используется этот метод. Считывание серийного номера с заголовком и конечным маркером

, 👍0

Обсуждение

sizeof-это элемент времени компиляции, сообщающий о байтах, которые что-то занимает. В данном случае это означает байты, которые использует числовое значение самого указателя. Если вы сами выделяете память, вам придется хранить ее отдельно. Рассмотрите возможность использования вектора c++., @Abel

@Abel В Arduino нет такой вещи, как вектор C++ - отсутствует STL., @Majenko

существуют реализации, которые должны работать достаточно хорошо. https://www.arduino.cc/reference/en/libraries/vector/, @Abel

@mehmet Пожалуйста, посмотрите мой ответ на предыдущий вопрос: http://arduinoprosto.ru/q/25317/22924, @John Burger


2 ответа


Лучший ответ:

4

Указатель-это просто указатель. Это не массив. На 8-битном ардуино диапазон адресов памяти равен 16-битному значению, поэтому указатель всегда будет 2 байта.

Вам нужно вернуть два значения из вашей функции - указатель буфера и длину буфера. Обычно это делается путем передачи дополнительного параметра целочисленного указателя:

unsigned long w;

void setup() {
  Serial.begin(9600);

  uint8_t plen;
  uint8_t * packet = read_packet(&plen); // Pass the pointer to the plen variable to store the length in

  Serial.println(plen); // This now prints "4"

  for (int i = 0; i < plen; i++) // You can now use `plen` here
  {
    Serial.println(packet[i]); //if i print the packet array all elements are here
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

uint8_t *read_packet(uint8_t *len) {

  static uint8_t buffer[4];

  buffer[0] = 0x00;
  buffer[1] = 0x32;
  buffer[2] = 0x32;
  buffer[3] = 0x32;

  if (len != NULL) *len = 4; // Store 4 in the length variable if provided

  return buffer;
}
,

просто быстрое добавление: поскольку arduino использует C++, можно использовать ссылку на массив "uint8_t (&буфер)[4]" для передачи фактического массива и правильной работы sizeof, а шаблон автоматически имеет массив не фиксированного размера и поддерживает проверку во время компиляции на правильность работы функций, подобных размеру и размеру, даже с помощью static_assert. Чрезвычайно мощный для управления размером массива, который функция может обрабатывать во время компиляции, @Lesto

@Лесто, конечно. Но это подразумевает некоторый уровень знаний со стороны программиста, чтобы даже знать, что такое ссылка или шаблон... И это Arduino..., @Majenko


1

Ответ Майенко объясняет вещи и показывает, как исправить ваш код, но решение со статическим буфером внутри функции не является распространенным.

Общим является наличие буфера чтения int(буфер unit8_t*, размер size_t).

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

Реальный пример:

int WiFiEspAtBuffStream::read(uint8_t* data, size_t size) {
  if (size == 0 || !available())
    return 0;

  size_t l = rxBufferLength - rxBufferIndex;
  if (l == 0 && size > rxBufferSize) // internal buffer is empty and provided buffer is large
    return EspAtDrv.recvData(linkId, data, size); // fill the large provided buffer directly

  // copy from internal buffer
  fillRXbuffer();
  for (size_t i = 0; i < l && i < size; i++) {
    data[i] = rxBuffer[rxBufferIndex++];
  }
  if (size <= l) // provided buffer was filled
    return size;
  return l + read(data + l, size - l); // handle the rest of provided buffer
}
,