如何访问整数的单个字节?

时间:2013-02-22 23:51:01

标签: c++ byte bit

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

我还没有看到一个明确的定义,但我认为它必须以网络字节顺序出现,所以在复制位之前我必须在内存中反转我的整数。 我仍然是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 个答案:

答案 0 :(得分: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

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

答案 1 :(得分: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);
}

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

答案 2 :(得分: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关于内置的自然尺寸的评论,并考虑使用固定宽度类型)。

答案 3 :(得分:0)

请检查libswiftnav存储库中实现的getbitu函数(链接复制如下)。想法是通过从ms位末尾提取然后移到最低有效位末尾来提取打包在多个字节中的值。它需要的输入是保存压缩值的缓冲区,值的字节偏移(相对于缓冲区的开头)以及要提取的值的位数。可以轻松地对函数进行模板化,以支持返回uint32以外的其他打包整数...添加一些状态以保存当前偏移量(此后在对getbitu的后续调用中递增),您可以通过重复发出轻松地将所有数据字段打包为打包消息按照特定的RTCM消息模式进行getbitu()。可移植,使值提取代码非常易读,并且可以立即解析新消息。

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