This question already has answers here:
What does |= mean in c++ [duplicate]
(2 answers)
Closed 6 years ago.
I am going through example code and found this operation:
displayMap[x + (y/8)*LCD_WIDTH]|= 1 (shift by) shift;
where
byte shift = y % 8;
I understand | operand and = but what are two of them together do.
| performs a bitwise OR on the two operands it is passed.
For example,
byte b = 0x0A | 0x50;
If you look at the underlying bits for 0x0A and 0x50, they are 0b00001010 and 0b01010000 respectively. When combined with the OR operator the result in b is 0b01011010, or 0x5A in hexadecimal.
|= is analogous to operators like += and -= in that it will perform a bitwise OR on the two operands then store the result in the left operator.
byte b = 0x0A;
b |= 0x50;
// after this b = 0x5A
Related
Let *c be 32bit in Memory and xmc[] array of 32bit in memory (abstract: Network packet)
xmc[0] = (*c >> 4) & 0x7;
xmc[1] = (*c >> 1) & 0x7;
xmc[2] = (*c++ & 0x1) << 2;
xmc[2] |= (*c >> 6) & 0x3;
xmc[3] = (*c >> 3) & 0x7;
What do the lines xmc[2] of code do to the Value (thought in binary)?
I tried to look up the arithmetic, but I failed understanding the part beginning from *c++.
EDIT: Added more context for clarification
Dereferencing and increment:
First, you are taking the value stored at the address pointed by the c pointer and incrementing the address.
Bitwise AND with a mask: A bitwise AND (&) is done with a mask of value 0x1 (decimal 1), which means that only the least significant bit is taken out of the value stored at the address c.
Think about it like that: You can have a variable on 4 bits, called a, with a decimal value of 3 (binary 0011) and you are doing a bitwise AND between a and a mask of decimal value 2 (binary 10), also on 4 bits (so 0010):
a = 0011
b = 0010
Bitwise AND (a & b or a & (0x10)) will compute an AND between each two bits from a and b. First bit in a is 1, first bit in b is 0 => least significant bit in the result is 1 & 0 = 0, go on with the second bits of each variable, leading to the second least significant bit in the result being 1, and so on...
AND with such a mask is typically used to take a certain bit (or a group of bits) from a value stored in a variable. In your case, your code takes the least significant bit stored in a.
Left shift: The left shift << takes the least significant bit two positions to the left (e.g. from 0001 to 0100), adding 2 bits on 0 to the right.
Let's assume that we operating on a unsigned 32 bit value. Then code
xmc[2] = (*c++ & 0x1) << 2;
is equivalent to
uint32_t tmp1 = *c; // Read the value that c points to and
c = c + 1; // increment the pointer c
// These two lines is the *c++ part
uint32_t tmp2 = tmp1 & 0x1; // Make tmp2 equal to the least significant bit of tmp1
// i.e. tmp2 will be 1 if tmp1 is odd and
// tmp2 will be 0 if tmp1 is even
uint32_t tmp3 = tmp2 << 2; // Make tmp3 equal to tmp2 shifted 2 bits to the left
// This is the same as: tmp3 = tmp2 * 4
xmc[2] = tmp3; // Save the result in xmc[2]
In pseudo code this means:
If the value pointed to be c is odd, set xmc[2] to 4
If the value pointed to be c is even, set xmc[2] to 0
Increment the pointer c
Today's date could be said to be 20230215.
If you have that as a number, you could extract the components as follows:
n = 20230215;
y = n / 10000 % 10000;
m = n / 100 % 100;
d = n / 1 % 100;
The code in question does the same thing. It's extracting four values (a, b, c and d) spread over two bytes.
c[0] c[1]
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
| | a | a | a | b | b | b | c | | c | c | d | d | d | | | |
+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
Since we want to extract bits instead of digits, we need to use powers of two instead of using powers of ten. When dealing with powers of two, >> can be used in lieu of division, and & can be used in lieu of %.
To extract a, b, c and d, we could use the following:
n = ( c[0] << 8 ) | c[1];
xmc[0] = ( n >> 12 ) & 0x7;
xmc[1] = ( n >> 9 ) & 0x7;
xmc[2] = ( n >> 6 ) & 0x7;
xmc[3] = ( n >> 3 ) & 0x7;
The posted code takes an approach that avoids calculating n, but it does the same thing.
++ is a post-increment operator in C language, and it would be the last operation before assigning a value to the left of the =.
xmc[2] = (*c++ & 0x1) << 2;
This statement could be considered to:
de-reference : *c
bit-wise AND : *c & 0x1
left-shift : (*c & 0x1) << 2
post-increment : c++
assign to left of = : xmc[2] = the result of the 3rd step.
But, the compiler would optimize these operations by its design and might increase c before the bit-wise AND operation by utilizing the registers of CPU and stacks in the memory. i.e. differences might be found in the final assembly code.
The posted code could be more easily read if it were, equivalently:
xmc[0] = (c[0] >> 4) & 0x7;
xmc[1] = (c[0] >> 1) & 0x7;
xmc[2] = (c[0] & 0x1) << 2;
xmc[2] |= (c[1] >> 6) & 0x3;
xmc[3] = (c[1] >> 3) & 0x7;
(And then, if later code depended on c being advanced, this could be followed by a standalone c++.)
It looks like xmc[0] is taken from three particular bits of c[0], and xmc[1] is taken from three other bits of c[0]. Then the next field straddles a word boundary, in that xmc[2] is composed by putting together one bit from c[0], and two bits from c[1]. Finally xmc[3] is taken from three other bits of c[1].
#ikegami's answer has more of the details.
i know that -> is a pointer |= is OR.
what is the logical meaning of such line?
TIMER0->ROUTELOC0 |= TIMER_ROUTELOC0_CC0LOC_LOC15
|= does not mean OR. | means OR.
|= is similar to +=, that is
A |= B is the equivalent of A = A | B
So to answer your question:
It looks like TIMER0 is a structure with a member ROUTELOC0. The above expression is setting the ROUTELOC0 as the result when ROUTELOC0 is ORed with TIMER_ROUTELOC0_CC0LOC_LOC15
You're ORing in (setting) a value to a register. Your processor has a TIMER0 with a register ROUTELOC0. It likely has a bit that is "CC0LOC_LOC15"
I recommend looking at the data sheet for your processor to figure out what that means specifically.
The -> is the structure dereference operator, and |= is the bitwise OR assignment operator (compound assignment).
The compound assignment:
x |= y ;
is equavilent to:
x = x | y ;
It is important here to understand that bitwise-OR (|) is distinct from boolean-OR (||). It is used here to set specific bits in x leaving other bits unset.
For example, to set the two least significant bits of x to 1:
x: 10100000
y: 00000011
---------
x|y: 10100011
Can you tell me what convertLedNumberToBit and LedDriver_TurnOn do? I do not understand what is happening with 1 << (num - 1) and |=
static uint16_t * ledsAddress;
static uint16_t convertLedNumberToBit(int ledNumber)
{
return 1 << (ledNumber - 1);
}
void LedDriver_TurnOn(int ledNumber)
{
*ledsAddress |= convertLedNumberToBit(ledNumber);
}
<< is a bitwise shift to the left. A uint16_t of 1 in binary is 0b0000000000000001, so when you shift left by the quantity ledNumber-1, the result is a uint16_t with a single-bit set to the position specified by ledNumber.
From the variable name ledNumber, I'm guessing that this function sets a specific LED to work on.
| performs a bitwise OR on the two operands it is passed.
For example,
byte b = 0x0A | 0x50;
If you look at the underlying bits for 0x0A and 0x50, they are 0b00001010 and 0b01010000 respectively. When combined with the OR operator the result in b is 0b01011010, or 0x5A in hexadecimal.
|= is a bitwise OR assignment. |= is analogous to operators like += and -= in that it will perform a bitwise OR on the two operands then store the result in the left operator.
byte b = 0x0A;
b |= 0x50;
// after this b = 0x5A
To switch 'ON' the LED[ledNumber] at I/O port ledsAddress, it is necessary to set the equivalent bit to '1'. But, when changing the I/O port value, you have to keep the state of all others LED still 'ON'.
The convertLedNumberToBit(int ledNumber) is using a mask b0000000000000001 (16bits) to set the ledNumber bit to '1' by switching to left of (ledNumber-1) { no shift needed when ledNumber is 1.
Ex: (ledNumber = 4) => returned value is b0000000000001000= 0x0008.
Then the call |= convertLedNumberToBit(ledNumber) will force only the ledNumber bit to '1' without changing others by a binary-OR.
Ex: (led1, led3 & led7 are 'ON')
before the OR b0000000001000101 = 0x0045.
LedDriver_TurnOn(4) => b0000000000001000= 0x0008
after the OR b0000000001001101 = 0x004D.
To switch 'OFF' the same LED, you have just to replace the OR function by the AND function of the NOT mask.
void LedDriver_TurnOff(int ledNumber)
{
*ledsAddress &= ~(convertLedNumberToBit(ledNumber));
}
cppreference - Arithmetic operators to the rescue
The bitwise shift operator expressions have the form
lhs << rhs (1)
lhs >> rhs (2)
1) left shift of lhs by rhs bits
2) right shift of lhs by rhs bits
So 1 << (ledNumber - 1) shifts the least significant bit to the left, e.g. if ledNumber = 5
0x0001 << (5 - 1)
will become
0x0010
Also cppreference - Assignment operators
|= is a (bitwise OR) assignment operator, where
*ledsAddress |= convertLedNumberToBit(ledNumber);
is equivalent to
*ledsAddress = *ledsAddress | convertLedNumberToBit(ledNumber);
This question already has answers here:
Check if a number x is positive (x>0) by ONLY using bitwise operators in C
(12 answers)
Closed 7 years ago.
int x1 =-2 ;//any value
if(x1 < 0)
x1 = 0;
I am trying by using bitwise operator
int result = !(x1 >> 31) & (((~x1 + 1) >> 31) & 1);
x1 = result !=0 ? x1:result;
I don't want to use the conditional operator to explore more use of binary operator .There is no any other intension behind this .If any way is there please let me know .
Is there any way to do so ??
Assuming 32 bit integer and two's compliment, would the following be OK?
unsigned int x = (unsigned int)-2;
x &= (x >> 31) - 1;
I used unsigned because according to the standard
The result of E1 >> E2 is E1 right-shifted E2 bit positions. .... If E1 has a signed type and a negative value, the
resulting value is implementation-defined.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
how to get bit by bit data from a integer value in c?
I have a 8-bit byte and I want to get a bit from this byte, like
getByte(0b01001100, 3) = 1
Firstoff, 0b prefix is not C but a GCC extension of C.
To get the value of the bit 3 of an uint8_t a, you can use this expression:
((a >> 3) & 0x01)
which would be evaluated to 1 if bit 3 is set and 0 if bit 3 is not set.
First of all C 0b01... doesn't have binary constants, try using hexadecimal ones. Second:
uint8_t byte;
printf("%d\n", byte & (1 << 2);
Use the & operator to mask to the bit you want and then shift it using >> as you like.