C++ Byte Stuff

Soldato
Joined
7 Apr 2004
Posts
4,212
Hey,

I was wondering if someone could explain to me how to put raw bytes into a variable of a specific type.

For example, I have a byte array with 2 elements, 0xFF and 0xFF. I want to put these into an unsigned short, which will equate to the maximum value of a unsigned short, 65535.

I worked out how to do this (google) using a shift and bitwise OR, it works but tbh i don't understand exactly what its doing on a bit level that makes it work.

Code:
	unsigned short v = data[0]; 
	v<<8|data[1];  //shift 8 bits & or it


Ok, with that said I also need to do the same with 8 Bytes -> double and 4 Bytes -> unsigned int, sadly I have no idea how to approach this
:p


Thanks for any help

Jack
 
Ok so you have an array with 2 indices that represents a 16bit unsigned short:

Code:
data[0]: 1111 1111 data[1]: 1111 1111

Transferring to a short we want to get this: 1111 1111 1111 1111

The first line sets a new short (v) to ONLY index 0, so you have a short that now contains the bits:

Code:
0000 0000 1111 1111

But index 0 was on the left most bits in your array, so you need to shift the short:

Code:
v << 8

v is now 1111 1111 0000 0000

Now, you do an OR with index 1, if you imagine data[1] as a 16bit short it is:

Code:
unsigned short temp = data[1];

temp is 0000 0000 1111 1111

You OR that with your short variable v:

Code:
0000 0000 1111 1111 == data[1]
1111 1111 0000 0000 == v
---------------------------------
1111 1111 1111 1111

So your short ends up with all 16bits at one. The bitwise OR simply takes 2 inputs, compares the bits, if either contain a 1 the result is a 1. If you need to know more about bitwise ops like this then google for truth tables and logic gates.

Did this help? :P

Edit: Another way to think of the OR in plain terms is that it is basically a way to join two bitsets together, not like a concatenation though, more like a merging. Like you are mashing one into another and the "1" bits win :P.
 
Last edited:
Thats brilliant, thanks very much :) Sure i can manage to do one for doubles and ints now that I can see what the shift was doing with the bits :)
 
hmmm, any ideas whats wrong with this:

Code:
unsigned int Container::BytesToUInt(const QByteArray& bytes)
{
	unsigned int result = 0;
	QByteArray input = bytes;
	input.resize(4); // enforce 4 bytes max
	
	// Convert to uint
	result = input[0];
	result << 8 | input[1];
	result << 8 | input[2];
	result << 8 | input[3];
	
	return result;
}

Cant think why it isnt working correctly, just repeating the bitwise shift and OR for all the 32bits :confused:


That should work like this shouldn't it?
Code:
0000 0000 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000 1111 1111 = input[0]

0000 0000 0000 0000 1111 1111 0000 0000 << 8
0000 0000 0000 0000 0000 0000 1111 1111 
--------------------------------------- | input[1]
0000 0000 0000 0000 1111 1111 1111 1111 

0000 0000 1111 1111 1111 1111 0000 0000 <<8
0000 0000 0000 0000 0000 0000 1111 1111 
--------------------------------------- | input[2]
0000 0000 1111 1111 1111 1111 1111 1111 

1111 1111 1111 1111 1111 1111 0000 0000 << 8
0000 0000 0000 0000 0000 0000 1111 1111
--------------------------------------- | input[3]
1111 1111 1111 1111 1111 1111 1111 1111

I however get very dogi values back.

0xFF, 0xFF, 0xFF, 0xFF returns 4294967295 correctly as expected
0x30, 0xFF, 0x20, 0xFF returns 48 which is clearly incorrect :(
 
Last edited:
Hhhhhm can you printf at each line, especially right after you do:

Code:
result = input[0];

I've a feeling we are having either some Endian or some sign extension issues here. Do you know what Endian the target platform is running?

Sometimes there's also a safer way to ensure correctness using a bitmask with an &, for instance you'd open up with:

Code:
result = input[0] & 0xFF;

to ensure that only the right most 8 bits are being set up. As you move up you'd be doing stuff like:

Code:
result = input[0] & 0xFF;
result = ((result << 8) | input[1]) & 0xFFFF;
result = ((result << 8) | input[2]) & 0xFFFFFF;
result = ((result << 8) | input[3]) & 0xFFFFFFFF;

I'm a little rusty on bitwise stuff but try those things and see what happens.
 
Thanks again, using your bitmask code combined with printfs (%X), i get the following output, from the 4 input bytes: 0x30, 0xFF, 0x20, 0xFF
Code:
Byte: 30   (result = input[0] & 0xFF;)
Byte: FFFF   (result = ((result << 8) | input[1]) & 0xFFFF;)
Byte: FFFF20   (result = ((result << 8) | input[2]) & 0xFFFFFF;)
Byte: FFFFFFFF   (result = ((result << 8) | input[3]) & 0xFFFFFFFF;)
Final Result: 4294967295

And for my code without the bitmasks i get:
Code:
Byte: 30
Byte: 30
Byte: 30
Byte: 30
Final Result: 48

Im using x86 hardware, so little-endian is in use which is ok with the code isnt it?

Any ideas, strange sutff :p?
 
Last edited:
Back
Top Bottom