Упаковывать биты и читать их - C - PullRequest
2 голосов
/ 02 декабря 2019

Вот объявления о том, что я отправляю на мой сервер:

typedef enum 
{
    GET = 0,
    SET = 1,
    UNDEF = 2,

} cmd_t;

struct  args 
{ 
    cmd_t cmd; 
    uint8_t value; 
    uint8_t id;
};

value имеет тип uint8_t и имеет, например, значение 42, а id также uint8_tи имеет значение 30. cmd - это мой typedef и, например, GET также 0.

Я отправляю эту информацию на сервер, упакованный так:

char buff[2];
buff[0] = arguments.cmd;
buff[0] += arguments.id << 2;

buff[1] = arguments.value;
send(sfd, buff, sizeof(buff), 0);

Я упаковываю первый байт в первые 2 бита моего cmd, затем сдвигаю его на 2 бита и упаковываю id. Затем на второй байт я упаковываю value. Я знаю, что значение не может быть больше 127, поэтому я могу оставить его в первых 7 битах моего байта. Я также знаю, что id не может быть лучше, чем 63.

Here is what I mean:

Затем я получаю это на моем сервере. Когда я читаю второй байт моего ответа, также req[1], я получаю значение 42, но когда я читаю свой первый байт, также req[0], однако я сдвигаю его, я не могу получить 0 или 30. требование объявлено как req[2]. Вот что я попробовал:

    for (size_t i = 0; i < 8; i++)
    {
       int idCMD = (uint8_t) (req[0]>>i);
       printf("idCMD -> %d\n", idCMD);
    }
    printf("\n");
     for (size_t i = 0; i < 8; i++)
    {
       int idCMD = (uint8_t) (req[0]<<i);
       printf("idCMD -> %d\n", idCMD);
    }

Как мне прочитать мой cmd и id?

output:

    idCMD -> 121
    idCMD -> 60
    idCMD -> 30
    idCMD -> 15
    idCMD -> 7
    idCMD -> 3
    idCMD -> 1
    idCMD -> 0

    idCMD -> 121
    idCMD -> 242
    idCMD -> 228
    idCMD -> 200
    idCMD -> 144
    idCMD -> 32
    idCMD -> 64
    idCMD -> 128

Из этого я получил следующее:

    printf("value -> %d\n", req[1]);
    printf("id -> %d\n", req[0] >> 2);
    printf("cmd-> %d\n", req[0] >> 6);

    value -> 42
    id -> 30
    cmd-> 1

Я понял, что cmd равно 1. Как мне убедиться, что я читаю 0, а не 1?

но, похоже, я не правильно читаю cmd. Вывод выше - это когда cmd равен 1. Вот когда cmd равен 0 и значение 0:

idCMD -> 120
idCMD -> 60
idCMD -> 30
idCMD -> 15
idCMD -> 7
idCMD -> 3
idCMD -> 1
idCMD -> 0

idCMD -> 120
idCMD -> 240
idCMD -> 224
idCMD -> 192
idCMD -> 128
idCMD -> 0
idCMD -> 0
idCMD -> 0
value -> 0
id -> 30
cmd-> 1

Как правильно прочитать cmd и это правильная интерпретация?

Ответы [ 2 ]

0 голосов
/ 02 декабря 2019

Если вы просто хотите легкий путь, это еще один выбор, объединение + структура

, вы можете определить, сколько битов на элемент в структуре

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef enum 
{
    GET = 0,
    SET = 1,
    UNDEF = 2,

} cmd_t;


union args_v2{
    uint8_t raw[2];

    struct {
        uint8_t cmd: 2;//2bits
        uint8_t id: 6;//6bits
        uint8_t value:  8;//8bits
    };
};
int main(){


    union args_v2 arguments_2;
    arguments_2.id=32;
    arguments_2.cmd=UNDEF;
    arguments_2.value=77;
    printf("\nPack Size%d\n",sizeof(arguments_2));
    printf("\nRaw %d %d\n",arguments_2.raw[0],arguments_2.raw[1]);//130=32*4+2
    //
    printf("\nid:%d cmd:%d value:%d\n",arguments_2.id,arguments_2.cmd,arguments_2.value);





    return 0;
}
0 голосов
/ 02 декабря 2019

Вот ты

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef enum 
{
    GET = 0,
    SET = 1,
    UNDEF = 2,

} cmd_t;

struct  args 
{ 
    cmd_t cmd; 
    uint8_t value; 
    uint8_t id;
};

int main(){
    char buff[2];
    struct  args arguments;
    arguments.cmd=UNDEF;
    arguments.id=23;//256/4=64 range 0~63



    buff[0] = arguments.cmd;
    buff[0] += arguments.id << 2;
    buff[1] = arguments.value;



    printf("%d\n",buff[0]&0b11);
    printf("%d",(buff[0]&0b11111100)>>2);
    return 0;
}
...