首页 > 解决方案 > 如何将结构中的一些信息打包到 2 字节缓冲区中?

问题描述

我有这种形式的结构:

struct args {
  uint16_t portnum;   /**< port number */
  const char *portstr;/**< port number as string */
  cmd_t cmd;          /**< command (GET, SET) */
  uint8_t value;      /**< set value */
  uint8_t id;         /**< device id */
};

struct args arguments =
    { DEFAULT_PORTNUM, DEFAULT_PORTNUM_STR, UNDEF, 0, 0 };

我需要从参数中提取“id,cmd,value”并将它们以这种形式保存在 2 字节缓冲区中:

图片

arguments.value 的最大值为 127,因此第 7 位未使用

我试过这个,但它不起作用

uint8_t buf[2];
buf[0] = arguments.cmd | arguments.id << 2;
buf[1] = arguments.value >> 1;

if(send(sockfd, buf, 2, 0) < 0 ){
   //error
}

标签: c

解决方案


cmd_t 是枚举 typedef enum { GET = 0, SET = 1, UNDEF = 2 } cmd_t;
ID ∈ [0, 63] ,
VALUE ∈ [0, 127]

只是不要value向右移动。>> 1(逻辑上)等于除以 2 / 2

buf[0] = arguments.cmd | arguments.id << 2;
buf[1] = arguments.value;

的 MSB 位buf[1]“未使用” - 将设置为零,从arguments.value.

请记住,最好实现断言或其他错误检查机制以使您的函数更加安全:

assert(0 <= arguments.cmd && arguments.cmd <= 2);
assert(0 <= arguments.id && arguments.id <= 63);
assert(0 <= arguments.value && arguments.value <= 127);

正如@bolson 在他的回答中所建议的那样,您可能会掩盖这些值,因此不会发生任何奇怪的事情

buf[0] = (arguments.cmd & 0x3) | ((arguments.id << 2) & 0xfc);
buf[1] = arguments.value & 0x7f;

推荐阅读