BitField1 = 00100110
BitField2 = 00110011
((BitField1 & ~BitField2) | (BitField2 & ~BitField1)); = 00010101
So this is the long version of a common bitwise operation, what is it?
Want to understand if above bit operation is some known operation ?
This is XOR. You end up with a 1 in those bits where either BitField1, or BitField2, but not both, have a 1.
As Wikipedia says, one use is
"Assembly language programmers sometimes use XOR as a short-cut to setting the value of a register to zero. Performing XOR on a value against itself always yields zero."
Related
Twos complement means that simply inverting all bits of a number i gets me -i-1:
~0 is -1
~01000001 is 10111110
~65 is -66
etc. To switch the sign of an integer, I have to use the actual minus sign.
int i = 65; int j = -i;
cout << j; // -65
Where is that actual behavior defined, and whose responsibility is it to ensure the twos complement pattern (to make a number negative invert all bits and add 1) is followed? I don't even know if this is a hardware or compiler operation.
It's usually done by the CPU hardware.
Some CPUs have an instruction for calculating the negative of a number. In the x86 architecture, it's the NEG instruction.
If not, it can be done using the multiplication operator, multiplying the number by -1. But many programmers take advantage of the identity that you discovered, and complement the number and then add 1. See
How to convert a positive number to negative in assembly
the reasons for this are simple: consistency with 0 and addition.
You want addition to work the same for positive and negative numbers without special cases... in particulary, incrementing -1 by 1 must yield 0.
The only bit sequence, where the classic overflowing increment produces the value of 0 is the all-1 bit sequence. If you increment by 1, you get all zeros. So that is your -1: all 1s, i.e. bitwise negation of 0.
Now we have (assuming 8 bit integers, incrementing by 1 each line)
-2: 11111110 = ~1
-1: 11111111 = ~0
0: 00000000 = ~-1
+1: 00000001 = ~-2
If you don't like this behavior, you need to handle special cases in addition, and you'll have +0 and -0. Most likely, such a CPU would be a lot slower.
If your question is how
int i = -j;
is implemented, that depends on your compiler and CPU and optimization. Usually it will be optimized together with other operations you specify. But don't be surprised if this ends up being performed as
int i = 0 - j;
Since this probably takes 1-2 cpu ticks to compute (e.g. as one XOR or a register onto itself to get 0, then a SUB operation to compute 0-j), it will barely ever be a bottleneck. Loading j and storing the result i somewhere in memory will be a lot lot lot more expensive. In fact, some CPUs (MIPS?) even have a built-in register that is always zero. Then you don't need a special instruction for negation, you simply subtract j from $zero in usually 1 tick.
Current Intel CPUs are said to recognize such xor operarions and do them in 0 ticks, with register renaming optimizations (i.e. they let the next instruction use a new register that is zero). You have neg on amd64, but a fast xor rax,rax is useful in other situations, too.
C arithmetic is defined in terms of values. When the code is:
int i = 65;
int j = -i;
the compiler will emit whatever CPU instructions are required to give j the value of -65, regardless of the bit representation.
Historically, not all systems used 2's complement. The C compiler would choose a system of negative numbers that leads to the most efficient output for the target CPU, based on the CPU's capabilities.
However 2's complement is a very common choice because it leads to the simplest algorithms for doing arithmetic. For example the same instruction can be used for + - * with signed and unsigned integers.
I know that this operator does the "AND logical operator" but I don't know how to deal with it and if it deals with decimal numbers or just binary numbers ?
It is the the XOR operator:
XOR (Exclusive Or)
This operation is performed between two bits (a and b). The result is
1 if either one of the two bits is 1, but not in the case that both
are. There for, if neither or both of them are equal to 1 the result
is 0.
That is the bitwise XOR operator.
It performs an exclusive or operation.
It is not the logical AND, it's the bitwise XOR. It operates on integers, which are always binary numbers in C++, and may be overloaded for other types.
That's the bitwise XOR operator (so not logical, not AND) and decimal numbers are represented as binaries, so of course it works for them as well.
The logical AND is && and the bitwise AND is &.
According to PC-lint, the following statement will never be TRUE:
if((variable & 0x02) == 1)
I am using a C compiler for embedded systems that evaluates it to TRUE whenever the corresponding bit in variable is set. I guess the compiler is doing a TRUE/FALSE comparison of both sides of the == instead of comparing the resulting numbers. In other words, every time the expression (varable & 0x02) is not zero (i.e. TRUE), the statement will also be TRUE, since the value 1 is also TRUE (not zero).
I don't know if the C/C++ standards clearly define how a compiler should behave in this case. Are there any C/C++ experts out there who can answer this question based on what the standards (e.g. C90, C99, etc.) say?
P.S.: In the statement above, "variable" is an unsigned char.
PC-lint is right. Assuming var is an integer variable, the expression var & 0x02 can evaluate to two values: 0 and 2. It will never be equal to 1, which is what the if statement is testing.
To expand on this, the equality operator is being applied to two integer values. What matters is whether both operands evaluate to the same number, not whether they're both simultaneously "true" or "false".
To test whether bit 1 is set, one could use:
if (variable & 0x02) {
...
}
Given that your compiler behaves the way you say it does, it's clearly non-compliant. However, it will almost certainly handle if (variable & 0x02) correctly. My recommendation would be to fix the code so it won't break silently if you were ever to change compilers.
Finally, the situation is different if: (1) the code is C++ and not C; and (2) variable is instance of a class; and (3) the class overloads the operators in question. In that case, the behaviour is down to what the overloaded operators actually do.
In C++, this can evaluate to a true value if (and only if) variable is an instance of a class with an overloaded operator& which does not conform to normal bitwise AND semantics.
In C, this condition will always be false. ยง6.5.10 defines the semantics of the bitwise AND operator, and it's quite simple and to the point:
4. The result of the binary & operator is the bitwise AND of the operands (that is, each bit in
the result is set if and only if each of the corresponding bits in the converted operands is
set).
It's clear that the result cannot be 1, as the 1 bit is not set in the converted value of the right-hand-side operand (namely, 0x02).
Naturally, if undefined behavior has been invoked at some point in the program's past (or at compile time!), then anything can happen. Barring this possibility, however, your compiler is non-compliant. That is to say, broken. This, unfortunately, is extremely common on odd embedded compilers. If you're lucky, you may even be able to report the bug and get it fixed.
I don't think the standard defines anything about this very specific and unusual issue. As said by aix, that statement can never be true because (in binary):
XXXX XXXX -> variable
0000 0010 -> 0x02
--------- AND
0000 00X0 -> result
(simplifying to 8-bit types)
So your only results can be 0000 0010 (which is 2) or 0000 0000 (which is 0).
For C, the answer is no.
The C standard says about & (6.5.10):
The result of the binary & operator is the bitwise AND of the operands (that is, each bit in
the result is set if and only if each of the corresponding bits in the converted operands is
set).
Since in 2 only the bit 1 is set, the value of the expression can only have set the bit 1. It can take no other values than 2 and 0. Neither 2 nor 0 can compare equal to 1.
The bit representations of integers are defined in 6.2.6.2 (for non-negative values in the usual way).
Basically, lint is right here. At least on any platform I know of, the condition will yield false. Look at the bit representation of the numbers: x & 2 (0010) will always be either zero or 2 (0010) and thus different from 1 (0001) for any integer x.
Let us consider the binary value of 2
02 = 0010 (say a 4 bit number)
and the binary value of 1 is
01 = 0001
The least significat bit of 2 is always zero that is the left most bit is 0. SO
The & (and) operation with 0 never gives 1 hence we can say it can never be equal to 1
0 0 => 0
0 1 => 0
1 1 => 1
Note: & indicates the bit wise and operation
2 - 0010
3 - 0011
0010
So the output with xx & 2 will be 0 or 2.
In this blog post the author has suggested the following as the bug fix:
int mid = (low + high) >>> 1;
Does anyone know what is this >>> operator? Certainly its not there on the following operator reference list:
http://msdn.microsoft.com/en-us/library/x04xhy0h%28v=vs.71%29.aspx
http://www.cplusplus.com/doc/tutorial/operators/
What is it and how does that solve the overflow problem?
>>> is not a part of C++. The blog contains code in Java.
Check out Java online tutorial here on Bitwise shift operators. It says
The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension.
>>> is the logical right shift operator in Java.
It shifts in a zero on the left rather than preserving the sign bit. The author of the blog post even provides a C++ implementation:
mid = ((unsigned int)low + (unsigned int)high)) >> 1;
... if you right-shift unsigned numbers, preserving the sign bit doesn't make any sense (since there is no sign bit) so the compiler obviously uses logical shifts rather than arithmetic ones.
The above code exploits the MSB (32rd bit assuming 32 bit integers): adding low and high which are both nonnegative integers and fit thus into 31 bits never overflows the full 32 bits, but it extends to the MSB. By shifting it to the right, the 32 bit number is effectively divided by two and the 32rd bit is cleared again, so the result is positive.
The truth is that the >>> operator in Java is just a workaround for the fact that the language does not provide unsigned data types.
The >>> operator is in a Java code snippet, and it is the unsigned right shift operator. It differs from the >> operator in its treatment of signed values: the >> operator applies sign extension during the shift, while the >>> operator just inserts a zero in the bit positions "emptied" by the shift.
Sadly, in C++ there's no such thing as sign-preserving and unsigned right shift, we have only the >> operator, whose behavior on negative signed values is implementation-defined. To emulate a behavior like the one of >>> you have to perform some casts to unsigned int before applying the shift (as shown in the code snippet immediately following the one you posted).
The Java expression x >>> y is more or less equivalent to the C++ expression unsigned(x) >> y.
>>> is not C++ operator. I think it's an operator in Java language. I'm not sure though!
EDIT:
Yes. That is java operator. Check out the link to the article you provided. The article is using Java language!
It is a java operator, not related to C++.
However all the blog author does is change the division by 2 with a bit-wise right shift (i.e. right shifting the value by 1 is similar to dividing by 2 ^ 1).
Same functionality, different machine code output (bit shifting operations are almost always faster than multiplication/division on most architectures).
I'm trying to write a function in assembly (but lets assume language agnostic for the question).
How can I use bitwise operators to set all bits of a passed in number to 1?
I know that I can use the bitwise "or" with a mask with the bits I wish to set, but I don't know how to construct a mask based off some a binary number of N size.
~(x & 0)
x & 0 will always result in 0, and ~ will flip all the bits to 1s.
Set it to 0, then flip all the bits to 1 with a bitwise-NOT.
You're going to find that in assembly language you have to know the size of a "passed in number". And in assembly language it really matters which machine the assembly language is for.
Given that information, you might be asking either
How do I set an integer register to all 1 bits?
or
How do I fill a region in memory with all 1 bits?
To fill a register with all 1 bits, on most machines the efficient way takes two instructions:
Clear the register, using either a special-purpose clear instruction, or load immediate 0, or xor the register with itself.
Take the bitwise complement of the register.
Filling memory with 1 bits then requires 1 or more store instructions...
You'll find a lot more bit-twiddling tips and tricks in Hank Warren's wonderful book Hacker's Delight.
Set it to -1. This is usually represented by all bits being 1.
Set x to 1
While x < number
x = x * 2
Answer = number or x - 1.
The code assumes your input is called "number". It should work fine for positive values. Note for negative values which are twos complement the operation attempt makes no sense as the high bit will always be one.
Use T(~T(0)).
Where T is the typename (if we are talking about C++.)
This prevents the unwanted promotion to int if the type is smaller than int.