Я пытаюсь извлечь определенную область моего сообщения и интерпретировать ее как структуру.
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 копирует байты с прямым порядком байтов, но я все еще не уверен, как решить проблему.
Вы всегда можете привести Sensor_buf к указателю char и получить доступ к отдельным членам. char *ptr = (char*)sensor_buf; for(int i = 0; i < 5; i++) { printf("%0xX \t", ptr[i]); }
@chux-ReinstateMonica Я могу опубликовать фактический код, но я пытаюсь упростить для читателей суть проблемы. Мое плохое о (, извините!
@н.м. извините за вопрос, но есть ли причина, по которой я не могу распечатать его как шестнадцатеричную интерпретацию напрямую? есть ли особые причины, по которым мы должны печатать каждый элемент отдельно? (в моем случае моя структура содержит только 5 данных uint8_t)
Ваш код незаконен, но то, что вы видите, скорее всего, является результатом %x ожидания 4 байтов и model_sensor_data_t 5 байтов... поэтому один байт никогда не печатается... Но просто повторю: ваш код незаконен, поэтому невозможно сказать что вообще происходит
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-битное шестнадцатеричное значение с обратным порядком байтов.
Если ESP_LOGI похоже на printf, то 0x%12x — это неправильный способ печати вашей структуры. Распечатайте каждый элемент отдельно.