Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one access a single byte of an integer?

Tags:

c++

byte

bit

For a specified communication standard RTCM SC104 3.1, I need to split data across bytes as a pair of 12 bit data segments. So for a given message I need to place the message type number on the first byte and half of the second byte. Then I need to start an ID integer on the half of second byte and continue to the third byte. This sort of pattern continues to the end of the message shaving down other integers in 20bit, 5bit, and other sizes essentially cutting of the 0's that would normally fill out the MSB end of the integer values.

I have not seen a clear definition but I assume it must go out in network byte order so before copying bits I would have to reverse my integers in memory. I am still quite new to cpp and am wondering how do I get to the individual bytes making up an integer in memory? If I can access the bytes then I could use bitwise or to split the bits from 2 bytes onto one for the message.

Here's the start of building a message before adding the data:

//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? 

The reference station will be from an unsigned short, so a 2 byte integer. So how do I go about reading a single byte from it? Do I start with a memory location pointer? If so then what?

Any help would be greatly appreciated.

like image 674
J Hinton Avatar asked Feb 22 '13 23:02

J Hinton


2 Answers

You can use bit fields, like this - some caveats at the end:

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

For me the main advantage is readability: all operations behave like regular operations on albeit narrower integral type variables. There are limitations (eg portability) but if you don't have to target multiple architectures or compilers or different endians it can help make your program a lot easier to read.

like image 138
fvu Avatar answered Sep 30 '22 09:09

fvu


If you have your integer looking like 00001000 00000000 11000000 00110000 for example (i'm making spaces to difference each single bytes), contained in example in an int a:

int     a;
int     single_byte;

a = the_number;

You could do a function like

int     get_byte_in_integer(int byte_number, int integer);

So that:

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

with

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

Hope this helps, for the byte part.

like image 33
SeedmanJ Avatar answered Sep 30 '22 09:09

SeedmanJ