memcpy 在复制到 struct 时丢失一个字节

问题描述 投票:0回答:1

我正在尝试提取消息的特定区域并将其解释为结构。

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-structC memcpy复制字节的字节序很少但我是仍然不确定如何解决这个问题。

c gcc struct communication espressif-idf
1个回答
1
投票
ESP_LOGI(TAG, "extracted sensor data is 0x%12x", *sensor_buf)

假设这是一个 printf-family 函数(似乎很可能),它将期待一个

unsigned int
作为参数,但是你传递了一个
model_sensor_data_t
,所以你会得到未定义的行为。

可能发生的情况是,

unsigned int
是一个 32 位小端值,在寄存器的底部 32 位中被访问,而您的调用约定将传递 64 位寄存器中的
model_sensor_data_t
,所以您将前 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 位大端十六进制值。

© www.soinside.com 2019 - 2024. All rights reserved.