如何访问整数的单个字节

How does one access a single byte of an integer?

本文关键字:整数 单个 字节 访问 何访问      更新时间:2023-10-16

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

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

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

//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字节的整数。那么我该如何从中读取一个字节呢?我是从内存位置指针开始的吗?如果是,那怎么办?

如有任何帮助,我们将不胜感激。

您可以使用位字段,如下所示-最后需要注意:

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

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

例如,如果您的整数看起来像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);
}

希望这对字节部分有所帮助。

您可以将其转换为字节,例如:

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关于内置的自然大小的评论,并考虑使用固定宽度类型)。

请检查在libswiftnav repo中实现的getbitu函数(链接如下)。想法是通过从ms比特端提取,然后向最低有效比特端移动,来提取跨多个字节打包的值。它需要的输入是保存压缩值的缓冲区、值的字节偏移量(相对于缓冲区的起点)和要提取的值的位数。这些函数可以很容易地被模板化,以支持返回uint32以外的压缩整数…添加一些状态来保持当前偏移量(在随后对getbitu的调用中会增加),并且可以通过根据特定的RTCM消息模式重复发出getbitu()来轻松地解压缩压缩消息中的所有数据字段。可移植,使值提取代码非常可读,并且可以很快完成解析新消息。

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