I have such code:
int value = 65536;
CString output = TEXT("");
output.Format(TEXT("%X"), value);
Printing output gives me: 10000
I need output like this: 0001.0000
Is it possible?
It seems to me I have found answer:
output.Format(TEXT("%.4X.%.4X"), (value >> 16) & 0xffff, value & 0xffff);
You have to mast byte you don't want and leave all others.
Assuming int is 32 bits on your platform you have:
Byte 4 3 2 1
Binary | 0000 0000 | 0000 0000 | 0000 0001 | 0000 0000 |
Hex 0x00 0x01 0x00 0x00
What you want is to isolate byte 1-2 and byte 3-4
Byte 1-2: simply mask all others bits using 0x0000FFFF or simply 0xFFFF
Byte 3-4: move left for 16 byts of bytes 1-2. Not your case but to be sure to print only value of those bytes mask all other bits.
Your code can be:
output.Format(TEXT("%04X.%04X"), (value >> 16) & 0xFFFF, (value & 0xFFFF));
Printing output gives me: 10000
The "%X" format string works just as expected.
I need output like this: 0001.0000
If I might ask, what's the point of using a floating point decimal representation? Hexadecimal is used because it translates directly to binary, otherwise there's no point using it.
But anyway if you really need it, the CString::format()'s formatting string is the same as printf()'s:
%A Hexadecimal floating point, uppercase
So replace %F by %A and cast your variable as a float it should do the trick!
Related
I've a function that takes int8_t val and converts it to int7_t.
//Bit [7] reserved
//Bits [6:0] = signed -64 to +63 offset value
// user who calls this function will use it correctly (-64 to +63)
uint8_t func_int7_t(int8_t val){
uint8_t val_6 = val & 0b01111111;
if (val & 0x80)
val_6 |= 0x40;
//...
//do stuff...
return val_6;
}
What is the best and fastest way to manipulate the int8 to int7? Did I do it efficient and fast? or there is better way?
The target is ARM Cortex M0+ if that matters
UPDATE:
After reading different answers I can say the question was asked wrong? (or my code in the question is what gave wrong assumptions to others) I had the intension to make an int8 to int7
So it will be done by doing nothing because
8bit:
63 = 0011 1111
62 = 0011 1110
0 = 0000 0000
-1 = 1111 1111
-2 = 1111 1110
-63 = 1100 0001
-64 = 1100 0000
7bit:
63 = 011 1111
62 = 011 1110
0 = 000 0000
-1 = 111 1111
-2 = 111 1110
-63 = 100 0001
-64 = 100 0000
the faster way is probably :
uint8_t val_7 = (val & 0x3f) | ((val >> 1) & 0x40);
val & 0x3f get the 6 lower bits (truncate) and ((val >> 1) & 0x40) move the bit to sign from the position 8 to 7
The advantage to not use a if is to have a shorter code (even you can use arithmetic if) and to have a code without sequence break
To clear the reserved bit, just
return val & 0x7f;
To leave the reserved bit exactly like how it was from input, nothing needs to be done
return val;
and the low 7 bits will contain the values in [-64, 63]. Because in two's complement down casting is done by a simple truncation. The value remains the same. That's what happens for an assignment like (int8_t)some_int_value
There's no such thing as 0bX1100001. There's no undefined bit in machine language. That state only exists in hardware, like the high-Z state or undefined state in Verilog or other hardware description languages
Use bitfield to narrow the value and let compiler to choose what sequence of shifts and/or masks is most efficient for that on your platform.
inline uint8_t to7bit(int8_t x)
{
struct {uint8_t x:7;} s;
return s.x = x;
}
If you are not concerned about what happens to out-of-range values, then
return val & 0x7f;
is enough. This correctly handles values in the range -64 <= val <= 63.
You haven't said how you want to handle out-of-range values, so I have nothing to say about that.
Updated to add: The question has been updated so stipulate that the function will never be called with out-of-range values. So this method qualifies unambiguously as "best and fastest".
the user who calls this function he knows he should put data -64 to +63
So not considering any other values, the really fastest thing you can do is not doing anything at all!
You have a 7 bit value stored in eight bits. Any value within specified range will have both bit 7 and bit 6 the same value, and when you process the 7-bit value, you just ignore the MSB (of 8-bit value), no matter if set or not, e. g.:
for(unsigned int bit = 0x40; bit; bit >>= 1)
// NOT: 0x80!
std::cout << (value & bit);
The other way round is more critical: whenever you receive these seven bits via some communication channel, then you need to do manual sign extension for eight (or more) bits to be able to correctly use that value.
I am currently working on a programming assignment in which I have to mask only a certain index of the whole 32-bit number(EX: If I take 8 4-bit numbers into my 32-bit integer, I would have 8 indices with 4 bits in each). I want to be able to print only part of the bits out of the whole 32 bits, which can be done with masking. If the bits were to only be in one place, I would not have a problem, for I would just create a mask that puts the 1s in a set place(EX: 00000000 00000000 00000000 00000001). However, I need to be able to shift the mask throughout only one index to print each bit (EX: I want to loop through the first index with my 0001 mask, shifting the 1 left every time, but I do not want to continue after the third bit of that index). I know that I need a loop to accomplish this; however, I am having a difficult time wrapping my head around how to complete this part of my assignment. Any tips, suggestions, or corrections would be appreciated. Also, I'm sorry if this was difficult to understand, but I could not find a better way to word it. Thanks.
first of all about representation. You need binary numbers to represent bits and masks. There are no binaries implemented directly in c/c++ languages at least before c++14. So, before c++14 you had to use hexadecimals or octals to represent your binaries, i.e.
0000 1111 == 0x0F
1111 1010 == 0xFA
since c++14 you can use
0b00001111;
Now, if you shift your binary mask left or right, you will have the following pictures
00001111 (OxF) << 2 ==> 00111100 (0x3C)
00001111 (0xF) >> 2 ==> 00000011 (0x03)
Now, supposedly you have an number in which you are interested in bits 4 to 7 (4 bits)
int bad = 0x0BAD; // == 0000 1011 1010 1101
you can create a mask as
int mask = 0x00F0; // == 0000 0000 1111 00000
and do bitwise and
int result = bad & mask; // ==> 0000 0000 1010 000 (0x00A0)
You will mask 4 bits in the middle of the word, but it will print as 0xA0. probably not what you would expect. To print it as 0xA you would need to shift the result 4 bits right: result >> 4. I prefer doing it in a bit different order, shifting the 'bad' first and then mask:
int result = (bad >> 4) & 0xF;
I hope the above will help you to understand bits.
Say I have a long 64 bit integer that starts with these bits:
0100 0000 0110 1101 .... .... ....
And I want a specific integer to hold this value:
0b10000000110
Which, as you can see are bits 2 through 12 in the original number.
How can I do this with bitwise operations is this possible?
Something like this should work:
uint64_t input = <0100 0000 0110 1101 .... .... ....>
uint64_t mask = (uint64_t)0x7FF << 52;
uint64_t output = (input & mask) >> 52;
0x7ff is eleven bits: 11111111111. Shift it left 52 bits to get it where you want, use it to mask the input value, and shift the return value back 52 bits.
Can anyone explain verbosely what this accomplishes? Im trying to learn c and am having a hard time wrapping my head around it.
void tonet_short(uint8_t *p, unsigned short s) {
p[0] = (s >> 8) & 0xff;
p[1] = s & 0xff;
}
void tonet_long(uint8_t *p, unsigned long l)
{
p[0] = (l >> 24) & 0xff;
p[1] = (l >> 16) & 0xff;
p[2] = (l >> 8) & 0xff;
p[3] = l & 0xff;
}
Verbosely, here it goes:
As a direct answer; both of them stores the bytes of a variable inside an array of bytes, from left to right. tonet_short does that for unsigned short variables, which consist of 2 bytes; and tonet_long does it for unsigned long variables, which consist of 4 bytes.
I will explain it for tonet_long, and tonet_short will just be the variation of it that you'll hopefully be able to derive yourself:
unsigned variables, when their bits are bitwise-shifted, get their bits shifted towards the determined side for determined amount of bits, and the vacated bits are made to be 0, zeros. I.e.:
unsigned char asd = 10; //which is 0000 1010 in basis 2
asd <<= 2; //shifts the bits of asd 2 times towards left
asd; //it is now 0010 1000 which is 40 in basis 10
Keep in mind that this is for unsigned variables, and these may be incorrect for signed variables.
The bitwise-and & operator compares the bits of two operands on both sides, returns a 1 (true) if both are 1 (true), and 0 (false) if any or both of them are 0 (false); and it does this for each bit. Example:
unsigned char asd = 10; //0000 1010
unsigned char qwe = 6; //0000 0110
asd & qwe; //0000 0010 <-- this is what it evaluates to, which is 2
Now that we know the bitwise-shift and bitwise-and, let's get to the first line of the function tonet_long:
p[0] = (l >> 24) & 0xff;
Here, since l is unsigned long, the (l >> 24) will be evaluated into the first 4 * 8 - 24 = 8 bits of the variable l, which is the first byte of the l. I can visualize the process like this:
abcd efgh ijkl mnop qrst uvwx yz.. .... //letters and dots stand for
//unknown zeros and ones
//shift this 24 times towards right
0000 0000 0000 0000 0000 0000 abcd efgh
Note that we do not change the l, this is just the evaluation of l >> 24, which is temporary.
Then the 0xff which is just 0000 0000 0000 0000 0000 0000 1111 1111 in hexadecimal (base 16), gets bitwise-anded with the bitwise-shifted l. It goes like this:
0000 0000 0000 0000 0000 0000 abcd efgh
&
0000 0000 0000 0000 0000 0000 1111 1111
=
0000 0000 0000 0000 0000 0000 abcd efgh
Since a & 1 will be simply dependent strictly on a, so it will be a; and same for the rest... It looks like a redundant operation for this, and it really is. It will, however, be important for the rest. This is because, for example, when you evaluate l >> 16, it looks like this:
0000 0000 0000 0000 abcd efgh ijkl mnop
Since we want only the ijkl mnop part, we have to discard the abcd efgh, and that will be done with the aid of 0000 0000 that 0xff has on its corresponding bits.
I hope this helps, the rest happens like it does this far, so... yeah.
These routines convert 16 and 32 bit values from native byte order to standard network(big-endian) byte order. They work by shifting and masking 8-bit chunks from the native value and storing them in order into a byte array.
If I see it right, I basically switches the order of bytes in the short and in the long ... (reverses the byte order of the number) and stores the result at an address which hopefully has enough space :)
explain verbosely - OK...
void tonet_short(uint8_t *p, unsigned short s) {
short is typically a 16-bit value (max: 0xFFFF)
The uint8_t is an unsigned 8-bit value, and p is a pointer to some number of unsigned 8-bit values (from the code we're assuming at least 2 sequential ones).
p[0] = (s >> 8) & 0xff;
This takes the "top half" of the value in s and puts it in the first element in the array p. So let's assume s==0x1234.
First s is shifted by 8 bits (s >> 8 == 0x0012)then it's AND'ed with 0xFF and the result is stored in p[0]. (p[0] == 0x12)
p[1] = s & 0xff;
Now note that when we did that shift, we never changed the original value of s, so s still has the original value of 0x1234, thus when we do this second line we simply do another bit-wise AND and p[1] get the "lower half" of the value of s (p[0] == 0x34)
The same applies for the other function you have there, but it's a long instead of a short, so we're assuming p in this case has enough space for all 32-bits (4x8) and we have to do some extra shifts too.
This code is used to serialize a 16-bit or 32-bit number into bytes (uint8_t). For example, to write them to disk, or to send them over a network connection.
A 16-bit value is split into two parts. One containing the most-significant (upper) 8 bits, the other containing least-significant (lower) 8 bits. The most-significant byte is stored first, then the least-significant byte. This is called big endian or "network" byte order. That's why the functions are named tonet_.
The same is done for the four bytes of a 32-bit value.
The & 0xff operations are actually useless. When a 16-bit or 32-bit value is converted to an 8-bit value, the lower 8 bits (0xff) are masked implicitly.
The bit-shifts are used to move the needed byte into the lowest 8 bits. Consider the bits of a 32-bit value:
AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD
The most significant byte are the 8 bits named A. In order to move them into the lowest 8 bits, the value has to be right-shifted by 24.
The names of the functions are a big hint... "to net short" and "to net long".
If you think about decimal... say we have a two pieces of paper so small we can only write one digit on each of them, we can therefore use both to record all the numbers from 0 to 99: 00, 01, 02... 08, 09, 10, 11... 18, 19, 20...98, 99. Basically, one piece of paper holds the "tens" column (given we're in base 10 for decimal), and the other the "units".
Memory works like that where each byte can store a number from 0..255, so we're working in base 256. If you have two bytes, one of them's going to be the "two-hundred-and-fifty-sixes" column, and the other the "units" column. To work out the combined value, you multiple the former by 256 and add the latter.
On paper we write numbers with the more significant ones on the left, but on a computer it's not clear if a more significant value should be in a higher or lower memory address, so different CPU manufacturers picked different conventions.
Consequently, some computers store 258 - which is 1 * 256 + 2 - as low=1 high=2, while others store low=2 high=1.
What these functions do is rearrange the memory from whatever your CPU happens to use to a predictable order - namely, the more significant value(s) go into the lower memory addresses, and eventually the "units" value is put into the highest memory address. This is a consistent way of storing the numbers that works across all computer types, so it's great when you want to transfer the data over the network; if the receiving computer uses a different memory ordering for the base-256 digits, it can move them from network byte ordering to whatever order it likes before interpreting them as CPU-native numbers.
So, "to net short" packs the most significant 8 bits of s into p[0] - the lower memory address. It didn't actually need to & 0xff as after taking the 16 input bits and shifting them 8 to the "right", all the left-hand 8 bits are guaranteed 0 anyway, which is the affect from & 0xFF - for example:
1010 1111 1011 0111 // = decimal 10*256^3 + 15*256^2 + 11*256 + 7
>>8 0000 0000 1010 1111 // move right 8, with left-hand values becoming 0
0xff 0000 0000 1111 1111 // we're going to and the above with this
& 0000 0000 1010 1111 // the bits that were on in both the above 2 values
// (the and never changes the value)
I am new at C, and I am debugging with source code. However, I am confused with this code snippet.
When the values are assigned to the structure value, I think it is some masking. But not sure, and if it is masking. How does masking work in this concept?
Many thanks,
#define MSGINFO_ENABLE 0x01
#define MIME_ENABLE 0x02
#define FASTSTART_CODERS_IN_OFFERED 0x04
#define TRANSADDR_ENABLE 0x08
typedef struct {
unsigned int msginfo_mask; /* added in version 0x0101 */
} VIRTBOARD;
VIRTBOARD VirtBoard;
/* Not sure I understand what is happening here. */
VirtBoard.msginfo_mask = MSGINFO_ENABLE | MIME_ENABLE | FASTSTART_CODERS_IN_OFFERED | TRANSADDR_ENABLE;
Ok in plain English:
The Hexdecimal numbers 0x01,0x02,0x04,0x08 were each selected BECAUSE they are each encoded as different single bits being set in binary. None of the bit maps overlap so each one can be read and set without being effected by the other bits. Adding the following comments to your code makes it clearer what's happening:
#define MSGINFO_ENABLE 0x01 // => 0001
#define MIME_ENABLE 0x02 // => 0010
#define FASTSTART_CODERS_IN_OFFERED 0x04 // => 0100
#define TRANSADDR_ENABLE 0x08 // => 1000
Now adding a comment before the other line shows the result:
// VirtBoard.msginfo_mask |= 0001
// VirtBoard.msginfo_mask |= 0010
// VirtBoard.msginfo_mask |= 0100
// VirtBoard.msginfo_mask |= 1000
// ----
// VirtBoard.msginfo_mask == 1111
VirtBoard.msginfo_mask = MSGINFO_ENABLE |
MIME_ENABLE |
FASTSTART_CODERS_IN_OFFERED |
TRANSADDR_ENABLE;
While the comments on the assignment make it clear what's going on, once you understand what's happening, the comments kinda defeat the purpose of symbolically defining constants.
It might help to think of it this way (values shown in binary):
MSGINFO_ENABLE = 0001
MIME_ENABLE = 0010
FASTSTART_CODERS_IN_OFFERED = 0100
TRANSADDR_ENABLE = 1000
So...
1001 is TRANSADDR_ENABLE and MSGINFO_ENABLE
or
1101 is eveything but FASTSTART_CODERS_IN_OFFERED
Does that help at all? The | notation is C syntax to set the correct bit:
int something = 0;
something = MSGINFO_ENABLE | TRANSADDR_ENABLE;
is the a syntax to set only those 2 bits.
Your variable, msginfo_mask, when represented as a binary number (1's and 0's) is used as a "mask" by setting certain bits to 1 (using bit-wise OR) or clearing certain bits to 0 (using bit-wise AND). Your code snippet sets certain bits to 1 while leaving others unchanged. Masking is comparable to how a painter masks off areas that they do not want to be painted.
If you look at the #defines at the top of your code, you will notice that each number represents a single bit when written out in binary:
#define MSGINFO_ENABLE 0x01 <-- 0001 in binary
#define MIME_ENABLE 0x02 <-- 0010 in binary
#define FASTSTART_CODERS_IN_OFFERED 0x04 <-- 0100 in binary
#define TRANSADDR_ENABLE 0x08 <-- 1000 in binary
Setting bits is done by using the OR function. If you OR a bit with 1, the result is always going to be a 1. If you OR a bit with 0, the original value will not be changed.
So, when you see:
msginfo_mask = MSGINFO_ENABLE | MIME_ENABLE |
FASTSTART_CODERS_IN_OFFERED | TRANSADDR_ENABLE;
What you are saying is "take the value of msginfo_mask and OR it with (binary) 0001, 0010, 0100, and 1000. This is the same thing as saying "set bit 0, bit 1, bit 2, and bit 3."
The binary operator '|' is the bitwise-or operator; for each bit in the two input words, if either bit is a 1, then the corresponding bit in the result is a 1:
0001 | 0010 = 0011
The '|' operator is typically used to set individual bits in a word, such as in the code snippet you posted.
The binary operator '&' is the bitwise-and operator; for each bit in the two input words, if both bits are 1, then the corresponding bit in the result is a 1:
0101 & 0110 = 0100
The '&' operator can be used to test if a bit is set. For example, to test if the MSGINFO_ENABLE bit is set, you'd do something like
if (VirtBoard.msginfo_mask & MSGINFO_ENABLE != 0)
{
/* MSGINFO_ENABLE bit is set, do something interesting */
}
The expression
VirtBoard.msginfo_mask & MSGINFO_ENABLE
will evaluate to 1 (0x0001) if the MSGINFO_ENABLE bit was set,0 otherwise.
The unary operator '~' is the bitwise-not operator; for each bit in the input word, the corresponding bit in the result is set to the opposite value:
~ 0001 = 1110
You can use the '~' operator together with the '&' operator to clear an individual bit. For example, if we wanted to clear the MSGINFO_ENABLE bit, we'd do something like
VirtBoard.msginfo_mask = VirtBoard.msginfo_mask & ~MSGINFO_ENABLE;
which can be shortened to
VirtBoard.msginfo_mask &= ~MSGINFO_ENABLE;
Negating MSGINFO_ ENABLE gives us 1111111111111110 (assuming a 16-bit unsigned int); since the leading bits are all 1, and-ing this against the VirtBoard.msginfo_ mask preserves any bits that are already set; i.e., 0000000000001111 & 1111111111111110 = 0000000000001110.
If we wanted to clear both the MSGINFO _ENABLE and TRANSADDR _ENABLE bits, we'd combine all the operators like so:
VirtBoard.msginfo_mask &= ~(MSGINFO_ENABLE | TRANSADDER_ENABLE)
The programmer is setting the mask to a certain bit value. In this case:
VitBoard.msginfo_mask = 0x01 | 0x02 | 0x04 = 0x07
Assuming the code handles messages, when a message comes in they may compare it to this mask to see what is enabled in the message.
if((newMsg & VitBoard.msginfo_mask) == 0x07)
{
//do something related to mime enable, msginfo enable and faststart
}
Notice the "&" operator to do the mask comparisons.
The other part is that "or" the masks together are probably being used as switches to enable/disable certain functionality. In the examples you have written, it looks like possibly output at different levels or parts of the codes.
The defined masks can be used to check the functionality to see if it is enable or disabled. For example:
VirtBoard.msginfo_mask = MSGINFO_ENABLE | MIME_ENABLE ;
if ( VirtBoard.msginfo_mask & MSGINFO_ENABLE )
{
printf("Messages enabled\n";
}
if ( VirtBoard.msginfo_mask & TRANSADDR_ENABLE)
{
printf("Transaddress enabled\n");
}
In the first if, since MSGINFO_ENABLED mask was "or" and assigned to the variable, when you apply an "and" operation with the variable and MSGINOF_ENABLED mask, a non zero value is returned, indicating it is true. So the printf statement will be executed.
In the case of the second if, since TRANSADDR_ENABLE was not "or" in to the variable, when an "and" is used with the variable and TRANSADDR_ENABLE mask, it will return a zero value, so no message will be printed.