6

对于指定的通信标准 RTCM SC104 3.1,我需要将数据跨字节拆分为一对 12 位数据段。因此,对于给定的消息,我需要将消息类型号放在第一个字节和第二个字节的一半上。然后我需要在第二个字节的一半开始一个 ID 整数并继续到第三个字节。这种模式一直持续到消息的末尾,它会减少 20 位、5 位和其他大小的其他整数,基本上是剪掉通常会填充整数值的 MSB 端的 0。

我还没有看到明确的定义,但我认为它必须以网络字节顺序输出,因此在复制位之前,我必须反转内存中的整数。我对 cpp 还是很陌生,想知道如何获取构成内存中整数的各个字节?如果我可以访问字节,那么我可以按位使用或将位从 2 个字节拆分为一个用于消息。

这是在添加数据之前构建消息的开始:

//build message 1002  gps 00111110 1010
    char buf1002[BUFFERSIZE];
    buf1002[0] = 0x3E; //00111110
    buf1002[1] = 0xA0; //10100000
//ref station id 12 bits of 16
//ex unsigned short m = 1100;
//m would be byte2 00000100 byte1 01001100
//buf1002[1] would be 10100100
//buf1002[2] would be 01001100
//reverse bit order for network after building? 

参考站将来自一个无符号短整数,因此是一个 2 字节整数。那么我该如何从其中读取单个字节呢?我是否从内存位置指针开始?如果是,那又如何?

任何帮助将不胜感激。

4

4 回答 4

4

您可以像这样使用位字段 - 最后有一些警告:

typedef union packet {
    struct {
        unsigned int msgno  : 12; // creates a 12 bit wide integral field
        unsigned int msgtype  : 12;
        unsigned int somefield2  : 3;
        unsigned int somefield3  : 5;
    } fields;

    unsigned char asbytes[4];
} packet;

...

packet p;
// fill it, by using the field side of the union
p.fields.msgno = 16;
p.fields.msgtype = 12;
p.fields.somefield2 = 6;
// and retrieving them as regular bytes
unsigned char abyte = p.asbytes[0];
abyte = p.asbytes[1];
// and so on

对我来说,主要优点是可读性:所有操作都像常规操作一样对更窄的整数类型变量进行操作。有一些限制(例如可移植性),但如果您不必针对多个体系结构或编译器或不同的字节序,它可以帮助您的程序更易于阅读。

于 2013-02-23T00:19:55.403 回答
2

例如,如果您的整数看起来像 00001000 00000000 11000000 00110000 (我正在制作空格来区分每个字节),则包含在 int a 的示例中:

int     a;
int     single_byte;

a = the_number;

你可以做一个像

int     get_byte_in_integer(int byte_number, int integer);

以便:

single_byte = get_byte_in_integer(1, a); // That would give you the 11000000 byte

int    get_byte_in_integer(int byte_number, int integer)
{
      return (integer >> (byte_number << 3)) & 0xff);
}

希望这有助于字节部分。

于 2013-02-23T00:08:07.757 回答
0

您可以将其作为字节双关,例如:

const unsigned short s(1);
const char* const bytes(reinterpret_cast<const char*>(&s));

const char NaturalOrder[sizeof(s)] = {bytes[0],bytes[1]};
const char EndianFlipped[sizeof(s)] = {bytes[1],bytes[0]};

(但另请参阅 dmckee 关于内置函数自然大小的评论,并考虑使用固定宽度类型)。

于 2013-02-22T23:58:18.600 回答
0

请检查 libswiftnav 存储库中实现的 getbitu 函数(链接转载如下)。想法是通过从 ms 位端提取然后移向最低有效位端来提取跨多个字节打包的值。它需要的输入是保存打包值的缓冲区、值的字节偏移量(相对于缓冲区的开头)和要提取的值的位数。这些函数可以很容易地被模板化以支持返回除 uint32 之外的打包整数...添加一些状态来保存当前偏移量(在随后的 getbitu 调用中递增),您可以通过重复发出轻松解压缩打包消息中的所有数据字段getbitu() 根据特定的 RTCM 消息模式。便携的,

https://github.com/swift-nav/libswiftnav/blob/master/src/bits.c

于 2019-12-25T03:18:39.773 回答