Bitwise AND in an If/Else block
-
If (ValueA And MaskA) = 0 Then ' or If Not (ValueA And MaskA) Then
After testing, the first example works, the second does not. For the first one, I see now the importance of hierarchy and the parens. For the second, I don't think it works because it is performing a binary NOT on the result, thus turning it into a negative number (or just a huge unsigned integer). At any rate, since it is now a non-zero number, the final condition is "True", and the intended action fails.treddie wrote:
After testing, the first example works, the second does not
Oh, it works, just not the way to think it does. The result of (ValueA And MaskA) results in an integer value, not True/False. That integer is compared to zero. If the result of the expression is non-zero, True is returned. The Not operator will invert that to False. If the result of the expression is zero, False is returned, then inverted to True by the Not operator. Withouting seeing the values of ValueA and Mask, it's pretty much all we can tell you.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak -
If (ValueA And MaskA) = 0 Then ' or If Not (ValueA And MaskA) Then
After testing, the first example works, the second does not. For the first one, I see now the importance of hierarchy and the parens. For the second, I don't think it works because it is performing a binary NOT on the result, thus turning it into a negative number (or just a huge unsigned integer). At any rate, since it is now a non-zero number, the final condition is "True", and the intended action fails. -
I have to admit, this is probably about as basic as it gets, but I must confess ignorance on this, and I cannot seem to find an answer anywhere. It goes like this: I have an If/EndIf block:
If ValueA And MaskA Then ' Do stuff. End if
Now, I look at that and my first reaction is to knee-jerk and expect that the above If-line is written incorrectly since a bitwise operation has been evaluated but no condition on it has been defined. In other words, I would expect it to be written more like:If ValueA And MaskA = 1 Then ' Do stuff. End if
I ran the first example and, indeed, it seemed to work OK. So then it seemed that vb.Net can treat such an expression in a special way, assuming that such a line before being evaluated is "0" (False) and then POSSIBLY, not zero AFTER evaluation, making the result "True". Then, based on that assumption, I needed a reverse logic, so that if the condition was False, it would execute rather than when it is True:If Not (ValueA And MaskA) Then ' Do stuff. End if
However, that does not work since all that does is essentially take the binary digits and flip them, turning the result into a negative value (a signed integer). So now it seems that the only solution is to set the block up as an If/Else block:If ValueA And MaskA Then ' Do stuff. Else ' Do alternate stuff. End if
That should ALWAYS work, I would tend to think. But if my above logic has been perfectly consistent, then the 2nd example in this post, should also work, but with a test for the value "0":If ValueA And MaskA = 0 Then ' Do stuff. End if
Alas, it failed, since vb.Net seems fixated on interpreting the result as having to be a Boolean, so my above logic is flawed somewhere. Even though evaluating the result in the Immediate window returns "0", the code does not execute. What IS the vb.Net convention for using bitwise operators in an If-conditional statement? Hopefully the answer to this question can solve the riddle of Global Warming and lead to cures for all diseases! :))Elimate the confusion and set "Option Strict On"; it is off in the default configuration. This will disallow the implied conversion from integer to boolean. see: Visual Studio compiler options, Part 2: Option Strict Also, review Operator Precedence in Visual Basic
-
treddie wrote:
After testing, the first example works, the second does not
Oh, it works, just not the way to think it does. The result of (ValueA And MaskA) results in an integer value, not True/False. That integer is compared to zero. If the result of the expression is non-zero, True is returned. The Not operator will invert that to False. If the result of the expression is zero, False is returned, then inverted to True by the Not operator. Withouting seeing the values of ValueA and Mask, it's pretty much all we can tell you.
A guide to posting questions on CodeProject[^]
Dave KreskowiakThe Not operator will invert that to False.
But that is not what happens. Here are some actual tests I performed:The value and the mask in these examples are:
FileAttributes Value that contains a bit field that indicates whether a resource is a folder or a file.
Folder = 8208D, File = 8224DMask Bit mask that tests for the presence of a folder (16D).
Option Strict is NOT set.
_____________________________________________________________________________________________________GOAL: Run code on "True" condition (Resource is a folder):
If (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
'Execute code.
End IfWhen FileAttributes = 8208D (Folder): 8208D (Folder) = 2 0 1 0 H 0010 0000 0001 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0001 0000 B <> 0, ("True"), Code executes as it should. When FileAttributes = 8224D (File): 8224D (File) = 2 0 2 0 H 0010 0000 0010 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0000 0000 B = 0, ("False"), Code does not execute. This is correct.
_____________________________________________________________________________________________________
GOAL: Run code on "False" condition (Resource is a file):
If Not (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
'Execute code.
End IfWhen FileAttributes = 8208D (Folder): 8208D (Folder) = 2 0 1 0 H 0010 0000 0001 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0001 0000 B <> 0, ("True"), Code WOULD execute, if left as is. \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ NOT 1111 1111 1110 1111 B <> 0, ("True"), Code executes when it SHOULD NOT. When FileAttributes = 8224D (File): 8224D (File) = 2 0 2 0 H 0010 0000 0010 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0000 0000 B = 0, ("False"), Code does not execute, if left as is. \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
-
The Not operator will invert that to False.
But that is not what happens. Here are some actual tests I performed:The value and the mask in these examples are:
FileAttributes Value that contains a bit field that indicates whether a resource is a folder or a file.
Folder = 8208D, File = 8224DMask Bit mask that tests for the presence of a folder (16D).
Option Strict is NOT set.
_____________________________________________________________________________________________________GOAL: Run code on "True" condition (Resource is a folder):
If (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
'Execute code.
End IfWhen FileAttributes = 8208D (Folder): 8208D (Folder) = 2 0 1 0 H 0010 0000 0001 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0001 0000 B <> 0, ("True"), Code executes as it should. When FileAttributes = 8224D (File): 8224D (File) = 2 0 2 0 H 0010 0000 0010 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0000 0000 B = 0, ("False"), Code does not execute. This is correct.
_____________________________________________________________________________________________________
GOAL: Run code on "False" condition (Resource is a file):
If Not (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
'Execute code.
End IfWhen FileAttributes = 8208D (Folder): 8208D (Folder) = 2 0 1 0 H 0010 0000 0001 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0001 0000 B <> 0, ("True"), Code WOULD execute, if left as is. \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ NOT 1111 1111 1110 1111 B <> 0, ("True"), Code executes when it SHOULD NOT. When FileAttributes = 8224D (File): 8224D (File) = 2 0 2 0 H 0010 0000 0010 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0000 0000 B = 0, ("False"), Code does not execute, if left as is. \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
OK. You should be testing the value of the bitwise operation against the value of the mask, NOT depending on an implied true or false.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak -
The Not operator will invert that to False.
But that is not what happens. Here are some actual tests I performed:The value and the mask in these examples are:
FileAttributes Value that contains a bit field that indicates whether a resource is a folder or a file.
Folder = 8208D, File = 8224DMask Bit mask that tests for the presence of a folder (16D).
Option Strict is NOT set.
_____________________________________________________________________________________________________GOAL: Run code on "True" condition (Resource is a folder):
If (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
'Execute code.
End IfWhen FileAttributes = 8208D (Folder): 8208D (Folder) = 2 0 1 0 H 0010 0000 0001 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0001 0000 B <> 0, ("True"), Code executes as it should. When FileAttributes = 8224D (File): 8224D (File) = 2 0 2 0 H 0010 0000 0010 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0000 0000 B = 0, ("False"), Code does not execute. This is correct.
_____________________________________________________________________________________________________
GOAL: Run code on "False" condition (Resource is a file):
If Not (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
'Execute code.
End IfWhen FileAttributes = 8208D (Folder): 8208D (Folder) = 2 0 1 0 H 0010 0000 0001 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0001 0000 B <> 0, ("True"), Code WOULD execute, if left as is. \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ NOT 1111 1111 1110 1111 B <> 0, ("True"), Code executes when it SHOULD NOT. When FileAttributes = 8224D (File): 8224D (File) = 2 0 2 0 H 0010 0000 0010 0000 B 16D (Mask) = AND 0000 0000 0001 0000 B \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Result 0000 0000 0000 0000 B = 0, ("False"), Code does not execute, if left as is. \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
That is the difference between a logical and a bitwise expression. In your expressions you cannot use
NOT
to invert from non-zero (impliedTRUE
) toFALSE
. I think as Dave suggests you need something like:If (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
' it is a directory.
Else
' it is NOT a directory.
End Ifor even
If (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY Then
' it is a directory.
Else
' it is NOT a directory.
End IfUse the best guess
-
That is the difference between a logical and a bitwise expression. In your expressions you cannot use
NOT
to invert from non-zero (impliedTRUE
) toFALSE
. I think as Dave suggests you need something like:If (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
' it is a directory.
Else
' it is NOT a directory.
End Ifor even
If (FileAttributes And FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY Then
' it is a directory.
Else
' it is NOT a directory.
End IfUse the best guess
That is the conclusion I came to in an earlier post. But I needed to understand why, and now I think I get the behavior. It's kind of like that old saying, "You can prove a positive, but you can't prove a negative." At least not without that extra Else clause thrown in.
-
Elimate the confusion and set "Option Strict On"; it is off in the default configuration. This will disallow the implied conversion from integer to boolean. see: Visual Studio compiler options, Part 2: Option Strict Also, review Operator Precedence in Visual Basic
-
That is the conclusion I came to in an earlier post. But I needed to understand why, and now I think I get the behavior. It's kind of like that old saying, "You can prove a positive, but you can't prove a negative." At least not without that extra Else clause thrown in.
treddie wrote:
It's kind of like that old saying, "You can prove a positive, but you can't prove a negative." At least not without that extra Else clause thrown in.
Well that's not quite the issue. The issue is that you are using a bitwise operation whose result will be some number of 1 bits, including zero. If you than apply the
NOT
operator (which is also a bitwise operator) to that result you will get the bitwise complement. Neither of these is a boolean expression so their results are neitherTRUE
norFALSE
, they are just some number of bits from 0 to hex FF etc. If the result has any bits set then it is generally assumed to beTRUE
in anIF
clause; if it has no bits set then it is assumed to beFALSE
. But applying theNOT
operator to a non-zero result, can still give a non-zero answer. If you want strict boolean tests then you must include a comparison operator in the expression, as I did in the second example of my previous answer.Use the best guess
-
treddie wrote:
It's kind of like that old saying, "You can prove a positive, but you can't prove a negative." At least not without that extra Else clause thrown in.
Well that's not quite the issue. The issue is that you are using a bitwise operation whose result will be some number of 1 bits, including zero. If you than apply the
NOT
operator (which is also a bitwise operator) to that result you will get the bitwise complement. Neither of these is a boolean expression so their results are neitherTRUE
norFALSE
, they are just some number of bits from 0 to hex FF etc. If the result has any bits set then it is generally assumed to beTRUE
in anIF
clause; if it has no bits set then it is assumed to beFALSE
. But applying theNOT
operator to a non-zero result, can still give a non-zero answer. If you want strict boolean tests then you must include a comparison operator in the expression, as I did in the second example of my previous answer.Use the best guess