Why use "|=","&=", etc. in C++ instead of"="?

I program Arduino and read about PORT on the Internet. They say that there will be some stability if you write instead of = - |=, or &=. So I did not understand why to write this way and how it differs from the usual"equal"? Here is an example of working code:

int main() {

DDRB = B00100000;

while(1) {
    PORTB |= B00100000;
    delay(1000);
    PORTB &= B00000000;
    delay(1000);
    }
}

If you replace all these |=, and &= with =, then everything will work exactly the same (as it seems to me) and the size of the firmware (sketch) will not even change. So back to the question: Why "|=", "& = " and etc. in c++?

Author: Kromster, 2018-03-26

4 answers

If the question concerns exactly c++, then these are operators.

|= - bitwise or with assignment. &= - bitwise and with assignment.

Learn more about the operators here

In fact, this is a simplified syntax for such a record:

a = a | b; // для |=
a = a & b; // для &=

I think it's a little clearer what equals has to do with it. Next, let's try to figure out what the | and & operators themselves are for. They are called bitwise or and bitwise and accordingly.

The | operator takes the bitwise representation of the operands, and as a result of executing this operator, you will get a number whose bitwise representation will contain units at those positions, on which at least one of the two bitwise representations of the operands had a unit. For example:

4 | 5 = 5;
// или (в побитовом представлении)
100 | 101 = 101;

Note that the leftmost and rightmost units are present in at least one of the binary representations of numbers, and so after executing the bitwise or, we have a number 101 (in binary) or 5 (in decimal).

The & operator takes the bitwise representation of the operands, and as a result of executing this operator, you will get a number whose bitwise representation will contain units at those positions, on which both bitwise representations of the operands had units. For example:

4 & 5 = 4;
// или (в побитовом представлении)
100 | 101 = 100;

Note that there is only one unit left, which is in both the first and right operands.

Well and coming very close to your task - | and & are usually used for working with bitwise flags. This is done to save space. For example, you have a variable of 4 bytes or 32 bits. In this case, you can store as many as 32 flags in this variable.

To add a flag, apply |:

int flags = 0;
// Добавим флаг на третьей справа позиции, ведь бинарное представление 4 - 100
flags |= 0x4; 

To check if there is a flag, you need to apply &:

// Бинарное и - по сути маска. И если на этой позиции была 1,
// то результат будет отличен от 0 и условие будет верным
if (flags & 0x4) {
    // сделать что-то
}

Something like that. Why does it work with equals? It's simple. With equal you are essentially erase the previous state of the variable with flags, and pass it only 1 flag along with equal. I hope you explained it clearly...

UPD by the way, in your case PORTB |= B00100000; adds a flag, and then PORTB &= B00000000; removes it (which is logical, because at the position where we put the flag, there is no unit in B00000000, and by applying and we essentially removed the flag).

UPD2 by the way, in pure c++ there are no literals of the form B00000000, this is a trick of the compiler arduino. In c++ starting from versions of 14 can use an entry of the form 0b00000000 to represent a binary literal.

 11
Author: selya, 2018-03-26 22:15:56

In your specific code-yes, it doesn't matter. Because you need for the entire variable to get one or another value.

But when programming all sorts of things - especially such things-these are very necessary operations.

Imagine that your PORTB is responsible for 8 LEDs at once. And you need, without changing the rest-which are glowing, let them glow, which are not-and remain-blink the third.

Let PORTB be, well, say, B10011010 - four LEDs are on

In your version, when assigning

PORTB = B00000100

You will extinguish them all by turning on the third one. Then turn everything off

PORTB = B00000000

But if you do this:

PORTB = PORTB | B00000100

And then

PORTB = PORTB & ~B00000100

The variable will get the values B10011110, and then become B10011010 again. That is, you are thus able to work with individual bits.

Well, and the entry

PORTB = PORTB | B00000100

A little shorter is written as

PORTB |= B00000100

A

PORTB = PORTB & ~B00000100

As

PORTB &= ~B00000100

If this is not clear, then I do not know what to do...

 5
Author: Harry, 2018-03-27 04:32:31

If you replace all these |=, and &= with =, then everything will work exactly the same

Nothing like this:

auto x{0x0E};
x &= 0x01;
assert(0 == x); 

auto y{0x0E};
y = 0x01;
assert(0x01 == y);

You can replace it with equal, but with the use of the bit operator:

auto z{0x0E};
z = z & 0x01;
assert(0x00 == z);
 0
Author: user7860670, 2018-03-26 21:47:42

I would like to add a simple example to the above. There is an array of numbers, but I don't need numbers, but I need the result: In what position are the odd numbers?

 int n[] = {1, 12, 33, 44, 5};
    for (int i = 0; i < 5; ++i) {
        n[i] &= 1;  // нечетным элементам присваиваем 1           
    }
  • Then the odd ones will be assigned 1, and the even ones !1, i.e. 0
  • And if you use |= instead of the &= operator, then 1 will be added to all odd numbers, and the array will look like 1, 13, 33, 45, 5
  • If you just assign, then all the elements will be units (of course) ...
 0
Author: AR Hovsepyan, 2018-03-27 09:04:43