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;
Related
I have a uint32_t as follows:
uint32_t midiData=0x9FCC00;
I need to separate this uint32_t into smaller parts so that 9 becomes its own entity, F becomes its own entity, and CC becomes its own entity. If you're wondering what I am doing, I am trying to break up the parts of a MIDI message so that they are easier to manage in my program.
I found this solution, but the problem is I don't know how to apply it to the CC section, and that I am not sure that this method works with C++.
Here is what I have so far:
uint32_t midiData=0x9FCC00;
uint32_t status = 0x0FFFFF & midiData; // Retrieve 9
uint32_t channel = (0xF0FFFF & midiData)>>4; //Retrieve F
uint32_t note = (0xFF00FF & midiData) >> 8; //Retrieve CC
Is this correct for C++? Reason I ask is cause I have never used C++ before and its syntax of using the > and < has always confused me (thus why I tend to avoid it).
You can use bit shift operator >> and bit masking operator & in C++ as well.
There are, however, some issues on how you use it:
Operator v1 & v2 gives a number built from those bits that are set in both v1 and v2, such that, for example, 0x12 & 0xF0 gives 0x10, not 0x02. Further, bit shift operator takes the number of bits, and a single digit in a hex number (which is usually called a nibble), consists of 4 bits (0x0..0xF requires 4 bits). So, if you have 0x12 and want to get 0x01, you have to write 0x12 >>4.
Hence, your shifts need to be adapted, too:
#define BITS_OF_A_NIBBLE 4
unsigned char status = (midiData & 0x00F00000) >> (5*BITS_OF_A_NIBBLE);
unsigned char channel = (midiData & 0x000F0000) >> (4*BITS_OF_A_NIBBLE);
unsigned char note = (midiData & 0x0000FF00) >> (2*BITS_OF_A_NIBBLE);
unsigned char theRest = (midiData & 0x000000FF);
You have it backwards, in a way.
In boolean logic (the & is a bitwise-AND), ANDing something with 0 will exclude it. Knowing that F in hex is 1111 in binary, a line like 0x9FCC00 & 0x0FFFFF will give you all the hex digits EXCEPT the 9, the opposite of what you want.
So, for status:
uint32_t status = 0xF000000 & midiData; // Retrieve 9
Actually, this will give you 0x900000. If you want 0x9 (also 9 in decimal), you need to bitshift the result over.
Now, the right bitshift operator (say, X >> 4) means move X 4 bits to the right; dividing by 16. That is 4 bits, not 4 hex digits. 1 hex digit == 4 bits, so to get 9 from 0x900000, you need 0x900000 >> 20.
So, to put them together, to get a status of 9:
uint32_t status = (0xF000000 & midiData) >> 20;
A similar process will get you the remaining values you want.
In general I'd recommend shift first, then mask - it's less error prone:
uint8_t cmd = (midiData >> 16) & 0xff;
uint8_t note = (midiData >> 8) & 0x7f; // MSB can't be set
uint8_t velocity = (midiData >> 0) & 0x7f; // ditto
and then split the cmd variable:
uint8_t status = (cmd & 0xf0); // range 0x00 .. 0xf0
uint8_t channel = (cmd & 0x0f); // range 0 .. 15
I personally wouldn't bother mapping the status value back into the range 0 .. 15 - it's commonly understood that e.g. 0x90 is a "note on", and not the plain value 9.
I have a unsigned short buffer , it contain a hexa values of IP header .
unsigned short buffer = {45,00,00,4E,4E,05,00,10,80,11,0X00,0X00,0A,00,00,1C,1A,00,00,2F};
I added 0X00 , 0X00 in the place of Checksum filed and calculated checksum with the RFC 1071 - Calculating IP header checksum . So it is returning a unsigned short checksum value . Now i need to insert to the Ip buffer .
For example : if my unsigned short checksum value = 55168 and it's Hex value = D780 . Now i need to add D7 , 80 to buffer[11] and buffer[12] . How can i convert unsigned short checksum value and split the Hex value for inserting to the buffer ? If it Hex = D78 , then also i need to add 0D and 78 to the buffer field .
You can separate the values using the bit operators
buffer[11] = (checksum >> 8) & 0xff;
buffer[12] = checksum & 0xff;
The first line shifts the checksum by 8 bits to the right, which is equivalent to dividing by 256 and than ensures, that you only get the information of those remaining 8 bits (0xD7) by using the and(&) operator with 0xff which equals to 1111 1111 in binary representation.
The second line also uses the and operator to save ONLY the last 8 bit of your checksum, which would be 0x80.
You can use expressions of the form buffer[11] = (checkSum & 0xFF00) >> 8; buffer[12] = (checkSum & 0xFF), but you should carefully check if your processor architecture uses big endian or little endian form for representing integers. Hence, it may be that on some systems you have to exchange the expressions to buffer[12] = (checkSum & 0xFF00) >> 8; buffer[11] = (checkSum & 0xFF).
See the following code:
#include <stdio.h>
unsigned short getCheckSum(unsigned short buffer[]) {
return 0xD780;
}
int main(int argc, const char *argv[])
{
unsigned short buffer[20] = {0x45,0x00,0x00,0x4E,0x4E,0x05,0x00,0x10,0x80,0x11,0X00,0X00,0x0A,0x00,0x00,0x1C,0x1A,0x00,0x00,0x2F};
unsigned short checkSum = getCheckSum(buffer);
buffer[11] = (checkSum & 0xFF00) >> 8;
buffer[12] = (checkSum & 0xFF);
for (int i=0; i<20; i++) {
printf("%02X ", buffer[i]);
}
return 0;
}
Given an unsigned integer, I need to end up with a 6-digits long hexadecimal value.
81892 (hex: 13FE4), should become 13FE40 or 013FE4
3285446057 (hex: C3D3EDA9), should become C3D3ED or D3EDA9
Since the project I'm contributing to uses Qt, I solve the problem this way:
unsigned int hex = qHash(name);
QString hexStr = (QString::number(hex, 16) + "000000").left(6);
bool ok;
unsigned int hexPat = hexStr.toUInt(&ok, 16);
This pads the hex number string on the right and then trims it after the sixth character from the left. To do the opposite, I would simply replace the second line:
QString hexStr = ("000000" + QString::number(hex, 16)).right(6);
The value will be used for RGB values, which is why I need six hex digits (three values between 0 and 255).
Is there a more efficient way to achieve either (or both) of these results without converting to string and then back?
The actual requirement for your problem is given an unsigned integer, you need to extract three bytes.
There really isn't any need to convert to a string to extract them, it can be more effectively performed using bit operations.
To extract any byte from the integer, right-shift (>>) the corresponding number of bits (0, 8, 16 or 24), and AND the result with a mask that takes only the rightmost byte (0xFF, which is really 0x000000FF).
e.g. take the three least significant bytes:
uint c = hash(...);
BYTE r = (BYTE)((c >> 16) & 0xFF);
BYTE g = (BYTE)((c >> 8) & 0xFF);
BYTE b = (BYTE)(c & 0xFF);
or three most significant bytes:
uint c = hash(...);
BYTE r = (BYTE)((c >> 24) & 0xFF);
BYTE g = (BYTE)((c >> 16) & 0xFF);
BYTE b = (BYTE)((c >> 8) & 0xFF);
I have an unsigned char and i want to write 0x06 on the four most significant, and i want to write 0x04 on its 4 least significant bits.
So the Char representation should be like 0110 0010
Can some can guide me how i can do this in C?
c = (0x06 << 4) | 0x04;
Because:
0x04 = 0000 0100
0x06 = 0000 0110
0x06<<4 = 0110 0000
or op: = 0110 0100
Shift values into the right position with the bitwise shift operators, and combine with bitwise or.
unsigned char c = (0x6 << 4) | 0x4;
To reverse the process and extract bitfields, you can use bitwise and with a mask containing just the bits you're interested in:
unsigned char lo4 = c & 0xf;
unsigned char hi4 = c >> 4;
First, ensure there are eight bits per unsigned char:
#include <limits.h>
#if CHAR_BIT != 8
#error "This code does not support character sizes other than 8 bits."
#endif
Now, suppose you already have an unsigned char defined with:
unsigned char x;
Then, if you want to completely set an unsigned char to have 6 in the high four bits and 4 in the low four bits, use:
x = 0x64;
If you want to see the high bits to a and the low bits to b, then use:
// Shift a to high four bits and combine with b.
x = a << 4 | b;
If you want to set the high bits to a and leave the low bits unchanged, use:
// Shift a to high four bits, extract low four bits of x, and combine.
x = a << 4 | x & 0xf;
If you want to set the low bits to b and leave the high bits unchanged, use:
// Extract high four bits of x and combine with b.
x = x & 0xf0 | b;
The above presumes that a and b contain only four-bit values. If they might have other bits set, use (a & 0xf) and (b & 0xf) in place of a and b above, respectively.
I'm having a little trouble grabbing n bits from a byte.
I have an unsigned integer. Let's say our number in hex is 0x2A, which is 42 in decimal. In binary it looks like this: 0010 1010. How would I grab the first 5 bits which are 00101 and the next 3 bits which are 010, and place them into separate integers?
If anyone could help me that would be great! I know how to extract from one byte which is to simply do
int x = (number >> (8*n)) & 0xff // n being the # byte
which I saw on another post on stack overflow, but I wasn't sure on how to get separate bits out of the byte. If anyone could help me out, that'd be great! Thanks!
Integers are represented inside a machine as a sequence of bits; fortunately for us humans, programming languages provide a mechanism to show us these numbers in decimal (or hexadecimal), but that does not alter their internal representation.
You should review the bitwise operators &, |, ^ and ~ as well as the shift operators << and >>, which will help you understand how to solve problems like this.
The last 3 bits of the integer are:
x & 0x7
The five bits starting from the eight-last bit are:
x >> 3 // all but the last three bits
& 0x1F // the last five bits.
"grabbing" parts of an integer type in C works like this:
You shift the bits you want to the lowest position.
You use & to mask the bits you want - ones means "copy this bit", zeros mean "ignore"
So, in you example. Let's say we have a number int x = 42;
first 5 bits:
(x >> 3) & ((1 << 5)-1);
or
(x >> 3) & 31;
To fetch the lower three bits:
(x >> 0) & ((1 << 3)-1)
or:
x & 7;
Say you want hi bits from the top, and lo bits from the bottom. (5 and 3 in your example)
top = (n >> lo) & ((1 << hi) - 1)
bottom = n & ((1 << lo) - 1)
Explanation:
For the top, first get rid of the lower bits (shift right), then mask the remaining with an "all ones" mask (if you have a binary number like 0010000, subtracting one results 0001111 - the same number of 1s as you had 0-s in the original number).
For the bottom it's the same, just don't have to care with the initial shifting.
top = (42 >> 3) & ((1 << 5) - 1) = 5 & (32 - 1) = 5 = 00101b
bottom = 42 & ((1 << 3) - 1) = 42 & (8 - 1) = 2 = 010b
You could use bitfields for this. Bitfields are special structs where you can specify variables in bits.
typedef struct {
unsigned char a:5;
unsigned char b:3;
} my_bit_t;
unsigned char c = 0x42;
my_bit_t * n = &c;
int first = n->a;
int sec = n->b;
Bit fields are described in more detail at http://www.cs.cf.ac.uk/Dave/C/node13.html#SECTION001320000000000000000
The charm of bit fields is, that you do not have to deal with shift operators etc. The notation is quite easy. As always with manipulating bits there is a portability issue.
int x = (number >> 3) & 0x1f;
will give you an integer where the last 5 bits are the 8-4 bits of number and zeros in the other bits.
Similarly,
int y = number & 0x7;
will give you an integer with the last 3 bits set the last 3 bits of number and the zeros in the rest.
just get rid of the 8* in your code.
int input = 42;
int high3 = input >> 5;
int low5 = input & (32 - 1); // 32 = 2^5
bool isBit3On = input & 4; // 4 = 2^(3-1)