Peculiarities of Bitwise Operations

<< Click to Display Table of Contents >>

Navigation:  Multi-Protocol MasterOPC Server > Lua 5.1 Reference Manual > Function library > The BIT Library >

Peculiarities of Bitwise Operations

When using bit operations, it is necessary to take into account peculiarities of Lua manipulations with numbers. When working with bits in C++, Pascal, ST or other languages, a number type and number dimension are declared explicitly - for instance, uint16 (unsigned short integer). In this case, being applied to such a number, any bit operator is applied only to bits of the number dimension.

In Lua. however, the only data type, number,  is provided for integers and reals. Number is a signed real of double precision (double). We cannot specify a number dimension, and this may lead to that a result might be incorrect. This concerns to the functions bit.BitNot and bit.BitLshift.

As an example, let's consider the use of the operator bit.BitNot. Assume that we need to invert bits of one byte. Let's declare a variable, initialize that variable, for example, by the number 10 (b00001010), and apply the operator bit.Not to that variable.

local k=10;

local z=bit.BitNot(k);

The variable z should take the value 245 (b11110101) but the code returns z= -11. Because of a type of number is a signed one, the number returned is negative. If such a number is used, for example, to estimate a check sum, the result will be incorrect.

In order to get a correct number, we need masking, using the operator bit.BitAnd. The first argument is the number we have to evaluate, and the second argument is a mask of meaningful bytes (in our case - 0xFF - b11111111).

local k=10;

local z=bit.BitAnd(bit.BitNot(k),0xFF);

Now z=245.

A similar situation can take place if we use the operator bit.BitLshift. Assume we have the 2-byte number 21763  (b01010101 00000011). Let's shift it to the left by 2 bits, using the operator bit.BitLshift.

local k=21763;

local z=bit.BitLshift(k,2);

The result should be b‭01010100 00001100‬‬ - 21516, but the server returns 87052 - b‭0001 01010100 00001100. What happened? If typing is strict, two upper bits shifted to the left would have been be erased. But Number is a signed real of double precision, and therefore a number dimension is increased instead. To solve such a problem, you can use masking as well, that is, execute the operator bit.BitAnd, using a mask of meaningful bits (0xFFFF - b11111111 11111111 in our case) as the second argument.

local k=21763;

local z=bit.BitAnd(bit.BitLshift(k,2),0xFFFF);

In this case. the server returns the correct value (unnecessary bits are zeroized).

We hope that you take into account peculiarities of Lua while working with bit operators.