Memcpy пропускает один байт при копировании в структуру

Я пытаюсь извлечь определенную область моего сообщения и интерпретировать ее как структуру.

void app_main(void)
{
  esp_err_t err;
  uint8_t injected_input[] = {0xCE,0x33,0xE1,0x00,0x11,0x22,0x33,0x44,0x55,0x66};
  model_sensor_data_t stuff = {0};
  model_sensor_data_t* sensor_buf = &stuff;
  if (extract_sensor_data_msgA(injected_input, sensor_buf) == -1)
  {
    ESP_LOGE(TAG, "Error in extract_sensor_data_msgA");
  }
  ESP_LOGI(TAG, "extracted sensor data is 0x%12x", *sensor_buf);

}
typedef struct __attribute__((packed))
{
  uint8_t byte0;
  uint8_t byte1;
  uint8_t byte2;
  uint8_t byte3;
  uint8_t byte4;
} model_sensor_data_t;

int32_t extract_sensor_data_msgA(uint8_t *buf, model_sensor_data_t *sensor_buf)
{
  if (buf == NULL || sensor_buf == NULL)
  {
    return -1;
  }
  //do other checks, blah blah

  memcpy(sensor_buf, buf + 5, sizeof(model_sensor_data_t)); //problem lies here 
  return 0;
}


Я ожидаю получить CLIENT: extracted sensor data is 0x2233445566, но я получаю CLIENT: extracted sensor data is 0x 55443322

Мне кажется, есть две проблемы, которые мне нужно исправить. Во-первых, это проблема порядка следования байтов, поскольку все извлеченные значения переворачиваются. Вторая проблема — это memcpy с отступами (?). Я думал, что вторая проблема будет исправлена, если я использую attribute((packed)) но, похоже, это не решает вторую проблему. Любая добрая душа может предоставить мне альтернативный способ решить эту проблему? Я сослался на https://electronics.stackexchange.com/questions/617711/problems-casting-a-uint8-t-array-to-a-struct и C memcpy копирует байты с прямым порядком байтов, но я все еще не уверен, как решить проблему.

Если ESP_LOGI похоже на printf, то 0x%12x — это неправильный способ печати вашей структуры. Распечатайте каждый элемент отдельно.

n. m. 20.02.2023 05:31

Вы всегда можете привести Sensor_buf к указателю char и получить доступ к отдельным членам. char *ptr = (char*)sensor_buf; for(int i = 0; i < 5; i++) { printf("%0xX \t", ptr[i]); }

Midhun Lohidakshan 20.02.2023 05:57

@chux-ReinstateMonica Я могу опубликовать фактический код, но я пытаюсь упростить для читателей суть проблемы. Мое плохое о (, извините!

Iberico 20.02.2023 07:14

@н.м. извините за вопрос, но есть ли причина, по которой я не могу распечатать его как шестнадцатеричную интерпретацию напрямую? есть ли особые причины, по которым мы должны печатать каждый элемент отдельно? (в моем случае моя структура содержит только 5 данных uint8_t)

Iberico 20.02.2023 07:15

Ваш код незаконен, но то, что вы видите, скорее всего, является результатом %x ожидания 4 байтов и model_sensor_data_t 5 байтов... поэтому один байт никогда не печатается... Но просто повторю: ваш код незаконен, поэтому невозможно сказать что вообще происходит

Support Ukraine 20.02.2023 07:27
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
1
5
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
ESP_LOGI(TAG, "extracted sensor data is 0x%12x", *sensor_buf)

Предполагая, что это будет функция семейства printf (вероятно), она будет ожидать unsigned int в качестве аргумента, но вы передаете model_sensor_data_t, поэтому вы получаете неопределенное поведение.

Что, вероятно, происходит, так это то, что unsigned int является 32-битным значением с прямым порядком байтов, доступ к которому осуществляется в нижних 32 битах регистра, в то время как ваше соглашение о вызовах будет передавать model_sensor_data_t в 64-битном регистре, поэтому вы видите первый 4 байта с прямым порядком байтов без знака. С другой стороны, printf ожидает 32-битное значение в стеке, а вы передаете 40-битное значение (вероятно, дополненное до 8 байтов для выравнивания). В любом случае, кажется почти уверенным, что вы используете машину с прямым порядком байтов, например x86 какой-то разновидности.

Чтобы напечатать это правильно, вам нужно напечатать каждый байт. Что-то вроде

ESP_LOGI(TAG, "extracted sensor data is 0x%02x%02x%02x%02x%02x", sensor_buf->byte0,
         sensor_buf->byte1, sensor_buf->byte2, sensor_buf->byte3, sensor_buf->byte4);

Распечатает извлеченные данные как 40-битное шестнадцатеричное значение с обратным порядком байтов.

Другие вопросы по теме