how to add two bits into a hex - c++

I have two bytes and I am setting different bits in order to get different combinations.
E.g, byte 1 bit 7 and byte 2 bit 1,bit 2 makes a combination device ready.
Now, I have created mask
#define C1_device_ready (0x80 | 0x100 | 0x200)
Then I read the data and try to compare.
for 1 byte I can do (data[0] & mask == mask).
But how can I compute it for C1_device_ready mask where there are two bytes, data[0]
and data[1].
Is it easily possible or should I do masking only in single byte.
::added::data is unsigned char data[2]

If data is an array of unsigned char, you could test
if ((data[0] & mask) == (mask & 0xFF) && (data[1] & mask) == ((mask >> 8) & 0xFF))
or combine the two data[i] and check
if (((data[0] | (data[1] << 8)) & mask) == mask)

Use
if (((data[0] | (data[1] << 8)) & mask) == mask) {
// do something
}

((data[0] | (data[1]<<8)) & mask) == mask
should work. Might need to cast things as unsigned int

Try:
if ((*(short *)data) & C1_device_ready)

Related

Reading bits from file

I can read for example , 4 bytes from file using
ifstream r(filename , ios::binary | ios::in)
uint_32 readHere;
r.read( (char*)&readHere, 4 )
But how could i read 4.5 bytes = 4bytes and 4 bits.
What came to my mind is
ifstream r(filename , ios::binary | std::in)
uint_64t readHere;
r.read( (char*)&readHere, 5 ) // reading 5 bytes ;
uint_64t tmp = readHere & 11111111 // extract 5th bytes
tmp = tmp >> 4 // get first half of the bites
readHere = (( readHere >> 8 ) << 8) | tmp // remove 5th byte then add 4 bits
But im not sure how shouldi take half of byte , if first or last 4.
Is there some better way how to retrieve it?
The smallest unit that you can read or write be it in file, or in memory is a char (a byte on common systems (*)). You can browse longer element byte wise, and effectively endianness matters here.
uint32_t u = 0xaabbccdd;
char *p = static_cast<char *>(&u);
char c = p[0]; // c is 0xdd on a little endian system and 0xaa on a big endian one
But as soon as you are inside a byte all you can do is to use bitwise ands and shifts to extract the low order or high order bits. There is no longer endianness here except if you decide to use one convention.
BTW, if you read on a network interface or even on a serial line where bits are individually transfered, you get one full byte at a time, and there is no way to read only 4 bits on one read and the 4 others on next one.
(*) older systems (CDC in the 80's) used to have 6bits per character - but C++ did not exist at that time and I'm unsure whether C compilers existed there
It's still not clear whether this is a file format that you control, or if it's something else. Anyway, let's assume you have some integer data type that can hold a 36-bit unsigned value:
typedef uint64_t u36;
Now, regardless of whether your system uses big-endian or little-endian, you can write the value to a binary stream in a predictable order by doing them one byte at a time. Let's use big-endian, because it's slightly easier to picture the bits assembling together to create a value.
You can just use naive shifting and masking into a small buffer. The only thing to decide is where to truncate the half-byte. But if you follow the pattern of shifting each value by another 8 bits, then the remainder naturally falls in the high-order.
ostream & write_u36( ostream & s, u36 val )
{
char bytes[5] = {
(val >> 28) & 0xff,
(val >> 20) & 0xff,
(val >> 12) & 0xff,
(val >> 4 ) & 0xff,
(val << 4 ) & 0xf0
};
return s.write( bytes, 5 );
}
But this isn't how you'd actually write a bunch of these numbers. You'd have to hold off the 5th byte until you were finished or you could pack the next value into it. Or you would always write two values at a time:
ostream & write_u36_pair( ostream & s, u36 a, u36 b )
{
char bytes[9] = {
(a >> 28) & 0xff,
(a >> 20) & 0xff,
(a >> 12) & 0xff,
(a >> 4 ) & 0xff,
(a << 4 ) & 0xf0 | (b >> 32) & 0x0f,
(b >> 24) & 0xff,
(b >> 16) & 0xff,
(b >> 8) & 0xff,
b & 0xff
};
return s.write( bytes, 9 );
}
And so now, you might see how to go about reading values and deserialising them back into integers. The simplest way is to read two at a time.
istream & read_u36_pair( istream & s, u36 & a, u36 & b )
{
char bytes[9];
if( s.read( bytes, 9 ) )
{
a = (u36)bytes[0] << 28
| (u36)bytes[1] << 20
| (u36)bytes[2] << 12
| (u36)bytes[3] << 4
| (u36)bytes[4] >> 4;
b = ((u36)bytes[4] & 0x0f) << 32
| (u36)bytes[5] << 24
| (u36)bytes[6] << 16
| (u36)bytes[7] << 8
| (u36)bytes[8];
}
return s;
}
If you wanted to read them one at a time, you'd need to keep track of some state so you knew how many bytes to read (either 5 or 4), and which shift operations to apply. Something naive like this:
struct u36deser {
char bytes[5];
int which = 0;
};
istream & read_u36( istream & s, u36deser & state, u36 & val )
{
if( state.which == 0 && s.read( state.bytes, 5 ) )
{
val = (u36)state.bytes[0] << 28
| (u36)state.bytes[1] << 20
| (u36)state.bytes[2] << 12
| (u36)state.bytes[3] << 4
| (u36)state.bytes[4] >> 4;
state.which = 1;
}
else if( state.which == 1 && s.read( state.bytes, 4 ) )
{
val = ((u36)state.bytes[4] & 0x0f) << 32 // byte left over from previous call
| (u36)state.bytes[0] << 24
| (u36)state.bytes[1] << 16
| (u36)state.bytes[2] << 8
| (u36)state.bytes[3];
state.which = 0;
}
return s;
}
All of this is purely hypothetical, which seems to be the point of your question anyway. There are many other ways to serialise bits, and some of them are not at all obvious.

Masking and shifting

Should we first shift the value then mask or the other way? And what is the risk in first masking before shifting?
((loc_Task_value_avg >> 8) & 0x00FF)
OR
((loc_Task_value_avg & 0xFF00) >> 8)
Try working through these kind of examples with real numbers. In this case, you'll find they do not result in the same output.
We'll use two examples.
First, suppose loc_Task_value_avg is equal to 0x1234
((loc_Task_value_avg >> 8) & 0x00FF)
((0x1234 >> 8 ) & 0x00FF)
(0x0012 & 0x00FF)
0x0012
vs
((loc_Task_value_avg & 0xFF00) >> 8)
((0x1234 & 0xFF00) >> 8)
(0x0012 >> 8)
0x0012
The danger comes when we are using signed values. Let's use 0xFEDC.
((loc_Task_value_avg >> 8) & 0x00FF)
((0xFEDC >> 8 ) & 0x00FF)
(0xFFFE & 0x00FF)
0x00FE
vs
((loc_Task_value_avg & 0xFF00) >> 8)
((0xFEDC & 0xFF00) >> 8)
(0xFE00 >> 8)
0xFFFE
The reason we get two separate outputs is because when dealing with signed values (Two's complement), shifting from the highest to lowest order value may result in the sign bit being extended. Whether this happens depends on whether the instructions by the compiler use signed or unsigned shift.
It depends on the size of the value you are shifting, the number of bits in the mask and whether the underlying value is signed or unsigned.
A shift-right is a divide by 2. On a signed value this means the sign bit will be preserved (because the underlying representation is most likely twos compliment). If your shift is large enough to shift copied sign bits into the masked result, it will make a difference.
If the underlying value is unsigned, it doesn't matter whether you shift then mask or mask then shift.
Each case would do different things.
Take the case with bits 1101.
If I mask the second bit (the zero) and then shift it one, then I would have the value 0.
On the other hand, if I shift the bits by one and then mask the second bit, I would have the value 1.
It is important to clearly identify what exactly you are intending to do and then go about from there.

How to store indivudual bits from a variable?

For example:
I got an input = 0x5A ( 0101 1010 ).
I want to store the first 4 bits or the last 4 bit.
unsigned char lower = input & 0xF;
unsigned char upper = (input >> 4) & 0xF;
Note that the last & 0xF is there in case your data type contains more bits than 8.
just use the & operator to apply a mask:
input = 0x5a & 0xf0;
this would yield 0b01010000. Depending on what you want you could shift the selected bits to the right like
input = (0x5a & 0xf0)>>4;
So to get to the lower half you would use
input = 0x5a & 0x0f;

C Bitwise Operation Question

Can someone help me understand whats going on with this code. It looks like it is making an integer from an array of bits. Im not sure how its doing that. Why is there a bitwise & operation on OxFF? Inst this just going to produce the same result?
//first take the first 4 bytes read out of the socket into an array and
//make them a 32 bit integer
long ltemp =0;
long ltemp2 = 0;
ltemp = ltemp | (unsigned char)(analog_val_ptr[0] & 0xff);
ltemp = ltemp << 24;
ltemp2 = ltemp2 | (unsigned char)(analog_val_ptr[1] & 0xff);
ltemp2 = ltemp2 << 16;
ltemp = ltemp2 | ltemp;
ltemp2 =0;
ltemp2 = ltemp2 | (unsigned char)(analog_val_ptr[2] & 0xff);
ltemp2 = ltemp2 << 8;
ltemp = ltemp2 | ltemp;
ltemp = ltemp | (unsigned char)(analog_val_ptr[3] & 0xff);
///then convert that integer into a float, passing
That's a very long-winded way of just converting four 8-bit bytes into a 32-bit long.
The anding with 0xff is just ensuring that only the lower 8 bits of each value are used (0xff == binary 11111111).
The bit-shifting (in multiples of 8) is just to get each character into the right position.
The whole thing could be replaced with something like:
unsigned long ltemp = (unsigned char)(analog_val_ptr[0] & 0xff);
ltemp = (ltemp << 8) | (unsigned char)(analog_val_ptr[1] & 0xff);
ltemp = (ltemp << 8) | (unsigned char)(analog_val_ptr[2] & 0xff);
ltemp = (ltemp << 8) | (unsigned char)(analog_val_ptr[3] & 0xff);
Or, alternatively (and assuming they're available), use the correct tools for the job, specifically htonl() and ntohl().
It looks like it's building an integer from an array of bytes. It may be that analog_val_ptr[] is an array of int or short values, and this code is designed to treat each entry as a byte. The masking is to prevent the sign bit from flooding the destination variable.
looks like it is going for an endian independent conversion.
var = 0x ? ? ? ? ? ? ? ?
& & & & & & & &
0x 0 0 0 0 0 0 f f
------------------
0 0 0 0 0 0 ? ?
After the AND operation the lower 8 bits will be found with var & 0xff. Its a way to only cut out the needed portion, masking.
The code above simply pastes the lower bytes of 4 array elements into the variable ltemp as a long int.

XOR higher 32 bits with lower 32 bits in a 64 bit number

In a 64 bit number How to XOR Higher order 32 bits with lower order 32 bits.
Thank you
(v & 0xffffffff) ^ ((v >> 32) & 0xffffffff)
Just for kicks, here's another solution. The one given already is probably the way to go.
uint32_t* number32;
uint64_t number64 = 0xffff1111ffffffff;
uint32_t xorValue;
number32 = (uint32_t*)&number64;
xorValue = number32[0]^number32[1];
uint32_t hi_low_xor(uint64_t x) {
return static_cast<uint32_t>(x) ^ static_cast<uint32_t>(x >> 32);
}
if you want to store the result in lower 32 bits:
(v & 0xffffffff) ^ ((v >> 32))
if you want to store the result in higher 32 bits:
((v & 0xffffffff) ^ ((v >> 32))) << 32