When I first leared how to write programs, I used C. (very basic command line applications) In both languages you use the ! - operator normally like this:
if(!true){
//false..
}
I wanted to do some bit-masking in c# and i wondered about the '~' operator.
Now i'm a bit confused because in my own understanding ! and ~ should do the same thing.
This works in c#:
int i = ~0xffffffff; // i = 0
bool j = !true; // j = false
This doesn't: (But it does work in c and does exactly what i expected)
int i = !0xffffffff; // i = 0
So what is the diffrence between ~ and ! and why did they separate them?
OR ( || ) - If EITHER or BOTH sides of the operator is true, the result will be true. AND ( && ) - If BOTH and ONLY BOTH sides of the operator are true, the result will be true.
The | operator evaluates both operands even if the left-hand operand evaluates to true, so that the operation result is true regardless of the value of the right-hand operand. The conditional logical OR operator ||, also known as the "short−circuiting" logical OR operator, computes the logical OR of its operands.
The && and || Operators in JavaScript. If applied to boolean values, the && operator only returns true when both of its operands are true (and false in all other cases), while the || operator only returns false when both of its operands are false (and true in all other cases).
C# made the decision to completely separate integer operations from boolean operations. You cannot for example do if(x & 4)
you must do if((x & 4) != 0)
to explicitly move from integers to booleans.
This is in line with over 4 decades of experience with C and its predecessors in which people have often made mistakes with it such as &ing two values that had a truth-value of true
and getting false
because while they where both non-zero they had no non-zero bits in common.
C and C++ both introduced a bool
type late in their history to add a more explicit difference between integers that represent either numbers or bit-patterns, and values where we only care about truth-values, but had to be compatible with older code. C# had the luxury of being even more explicit.
With that in mind, C#'s !
and ~
are exactly the same as in C, except that some things no longer make sense:
In C !
negates truth value. It turns 0 (false) into 1 (true) and everything non-zero (true) into 0 (false). In C# that only makes sense with bool
, not with int
.
In C ~
produces the one's-complement; It produces a value where every 1 bit is turned to 0 and every 0 bit is turned to 1 (e.g. 0xFFFFFFFF becomes 0, 0xF0F0F0F0 becomes 0x0F0F0F0F and so on). In C# that makes sense with int
, but not with bool
.
If you want to do the equivalent of !someInteger
in C#, do someInteger == 0
.
Edit:
It's worth noting that there is sometimes some confusion caused by the operators being split into "bitwise" ('&', '|' and '~') and "boolean" ('&&', '||' and '!'). This distinction is not quite correct.
Now, the last three do indeed only make sense in boolean contexts, and so with C# having a stricter separation between boolean and integer values, they are no longer applied to integers.
'~' does indeed not make sense in boolean contexts ('~x' where 'x' is true will produce an 'x' that is still true, 4294967294 times out of 4294967295), and so with C# it's no longer applied to bools.
'&' and '|' retain a boolean use though. In the case where 'A()' and 'B()' each return a bool
, then while A() && B()
will only call B()
if A()
is false (that is, it "short-circuits"), A() & B()
will always call both methods, before doing the ∧
Boolean arithmetic. This tends to be rare because:
Most of the time calling B()
is just a waste of time, and short-circuiting can give us a performance boost ranging from massive (if B()
is expensive) through to made-no-difference-but-we-didn't-lose-anything-anyway, so it's the habit to be in. (But consider that if B()
is very cheap the cost of calling it anyway might be cheaper than the branch, especially if mispredicted, see comments below).
Sometimes &&
is compulsory such as in x != null && x.Length != 0
where not short-circuiting would throw an exception on the second argument.
If it's that important to make sure both methods were called, then it's better coding to do this in separate statements, to make that clear to other developers (or yourself when you come back later).
But if we're going to talk about the difference between operators with boolean and integer arguments, we should include the boolean use of |
and &
, because they do come up (sometimes through typos!), and they can cause confusion if people are falsely separating "bitwise operators" and "boolean operators" and forgetting that there are two symbols that are used as both.
!
is a boolean invert, it inverts a value from true
to false
and vice versa.
http://msdn.microsoft.com/en-us/library/f2kd6eb2.aspx
~
is a bitwise invert, it inverts every bit of an integral value, like int i
.
http://msdn.microsoft.com/en-us/library/d2bd4x66.aspx
see http://msdn.microsoft.com/en-us/library/6a71f45d.aspx for full guide on all operators.
The reason why !
and ~
are separate is because they do different things.
~
The bitwise NOT operator is a unary operator, as it includes single operand. Unlike the other bitwise operators, the bitwise version does not use the same symbol as the similar Boolean operator. To achieve a one's complement, the tilde character (~) is positioned to the left of the value to modify.
byte valueToComplement = 187; // 10111011
byte complement = (byte) ~valueToComplement; // Result = 68
!
- is a boolean invert which can be either true or false.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With