Identifying a specific binary number with bitmask - c#

I am trying to identify states in a CANopen motor controller using the following bit masks.
//x means that the value of the bit doesn't matter and is set to 0
NOT_READY_TO_SWITCH_ON = 0, //xxxx xxxx x0xx 0000 - Not ready to switch on (decimal value = 0)
SWITCH_ON_DISABLED = 64, //xxxx xxxx x1xx 0000 - Switch on disabled (decimal value = 64)
READY_TO_SWITCH_ON = 33, //xxxx xxxx x01x 0001 - Ready to switch on (33)
SWITCHED_ON = 35, //xxxx xxxx x01x 0011 - Switched on (35)
OPERATION_ENABLED = 39, //xxxx xxxx x01x 0111 - Operation enabled (39)
QUICK_STOP_ACTIVE = 7, //xxxx xxxx x00x 0111 - Quick stop active (7)
FAULT_REACTION_ACTIVE = 15, //xxxx xxxx x0xx 1111 - Fault reaction active (15)
FAULT = 8, //xxxx xxxx x0xx 1000 - Fault (8)
I am receiving a number on which I apply the bit mask to try to identify the states above but I can't wrap my head around how it should be done.
The following code is my attempt to implement it in C#:
foreach (State s in (State[]) Enum.GetValues(typeof(State))) //State[] contains all bitmasks above
{
var v = valToCheck & (ushort)s; //valToCheck is the number to apply the bitmask to
if ((valToCheck & (ushort)s) == (ushort)s) //Apply the bitmask and compare it to bitmask
{
stateList.Add(s); //Add to list for trouble. shooting
}
}
But doing it this way I end up with, instead of one, a bunch of states which is, I guess, expected since applying for example, the bitmask 0 (NOT_READY_TO_SWITCH_ON) will always yield true for any number (when using and).
Am I doing something fundamentally wrong or is this simply not possible using bit masks? I am also unsure if it is correct to set the bits marked with x to 0 in the masks.

You're right - you can't test for 0 with masks; presumably the intent is that all zero has special meaning that only matches this flag, so you would special case it by testing for equality with zero instead:
if (thingToLookFor == 0) return value == 0;

Related

Is ampersand followed by int.MaxValue rounding down?

I have a piece of C# code that another developer has copied from a blog post which is used to encode/obfuscate an integer. this code contains some syntax that i am unfamiliar with. It looks like it might be rounding down the result of the calculation to prevent it from exceeding the maximum size of an integer, if that is the case i am worried that two input values could potentially result in the same output. The obfuscated values need to be unique so i'm worried about using this code without understanding how it works
this is a simplified version of the code:
public static int DecodeNumber(int input)
{
return (input * PrimeInverse) & int.MaxValue;
}
so my question is
what is the meaning of the ampersand in this context and will this code produce an output that is unique to the input?
No, there is no "rounding" going on here. This is a sneaky way of truncating the most significant bit when multiplication results in overflow.
According to the documentation, int.MaxValue is 2,147,483,647, which is 0x7FFFFFFF in hex. Performing a bitwise AND with this value simply clears out the most significant bit.
Since the intention of the code is to use int.MaxValue for its binary pattern, rather than for its numeric value of the highest int that could be represented by Int32, I would recommend either using 0x7FFFFFFF constant explicitly, or computing it with ~ expressionL
return (input * PrimeInverse) & ~(1 << 31);
The ampersand is a bitwise AND operator. The numbers on the sides of this operator will be considered in binary format and a logic AND would be performed on the bits of the same significance.
The int.MaxValue equals 2,147,483,647. The result of this operation is explained as below:
operation:
a = x & int.MaxValue;
result:
if (x >= 0) {a = x;}
if (x < 0) {a = x + 2,147,483,648;}
if x is non-negative then a = x;
if x is negative, then a = x + 2,147,483,648;
EDIT :
Logical Operations:
Logical operations like AND, OR, XOR, etc are defined to work on Boolean (logical) values. Boolean variables can have either 1 or 0 as their values. The result of AND operation between two logical variables will be 1 if and only if both the variables are equal to 1. This is shown below:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
Bitwise AND operator on numbers works using the basic AND operator. First the two numbers on the sides of operator are converted to binary format. If the number of digits in both numbers are not equal, zeros are added to the left side of the number with less number of digits to have the same number of digits for both numbers. Then the digits of the same significance are ANDed one by one the way explained above and the result of each operation will be written on the place with the same significance constructing the result. The bitwise and between 12 and 7 is shown below. 12 is demonstrated as 1100 in binary format and 7 is 0111.
12 = 0b1100
7 = 0b0111
12 & 7 = ?
1 1 0 0 &
0 1 1 1
----------
0 1 0 0 = 4

C# hexadecimal & comparison

I ran into a bit of code similar to the code below and was just curious if someone could help me understand what it's doing?:
int flag = 5;
Console.WriteLine(0x0E & flag);
// 5 returns 4, 6 returns 4, 7 returns 6, 8 returns 8
Sandbox:
https://dotnetfiddle.net/NnLyvJ
This is the bitwise AND operator.
It performs an AND operation on the bits of a number.
A logical AND operation on two [boolean] values returns True if the two values are True; False otherwise.
A bitwise AND operation on two numbers returns a number from all the bits of the two numbers that are 1 (True) in both numbers.
Example:
5 = 101
4 = 100
AND = 100 = 4
Therefore, 5 & 4 = 4.
This logic is heavily used for storing flags, you just need to assign each flag a power of 2 (1, 2, 4, 8, etc) so that each flag is stored in a different bit of the flags number, and then you just need to do flags & FLAG_VALUE and if the flag is set, it'll return FLAG_VALUE, otherwise 0.
C# provides a "cleaner" way to do this using enums and the Flags attribute.
[Flags]
public enum MyFlags
{
Flag0 = 1 << 0, // using the bitwise shift operator to make it more readable
Flag1 = 1 << 1,
Flag2 = 1 << 2,
Flag3 = 1 << 3,
}
void a()
{
var flags = MyFlags.Flag0 | MyFlags.Flag1 | MyFlags.Flag3;
Console.WriteLine(Convert.ToString((int) flags, 2)); // prints the binary representation of flags, that is "1011" (in base 10 it's 11)
Console.WriteLine(flags); // as the enum has the Flags attribute, it prints "Flag0, Flag1, Flag3" instead of treating it as an invalid value and printing "11"
Console.WriteLine(flags.HasFlag(MyFlags.Flag1)); // the Flags attribute also provides the HasFlag function, which is syntactic sugar for doing "(flags & MyFlags.Flag1) != 0"
}
Excuse my bad english.

What is Enum.HasFlag supposed to return?

I have the enum:
[Flags]
enum Editions
{
Educational,
Basic,
Pro,
Ultra
}
why do I get this behavior?
var x = Editions.Basic;
var y = Editions.Educational;
var test =x.HasFlag(y); // why is this true!?
// and!!!
var test2 = y.HasFlag(x); // this is false!
When using the [Flags] attribute you should explicitly map the enum values to integer that contain non overlapping bit patterns. That is, each enum value should be mapped to a power of two:
[Flags]
enum Editions
{
Educational = 1,
Basic = 2,
Pro = 4,
Ultra = 8
}
Without the explicit numbering, Educational will be mapped to 0 and Basic to 1.
Enum.HasFlags checks if the bit field or bit fields that are set in the parameter are also all set in the tested enum. In your case, x is 1 and y is 0. That means that x contains all of the bits set in 0 (that is no bits at all). However 0 does not contain the bits set in 1 when testing the other way around.
It returns true because you implemented Editions incorrectly. You must explicitly set the values when you use the [Flags] attribute.
[Flags]
enum Editions
{ //binary format
Educational = 1 << 0, // 0001
Basic = 1 << 1, // 0010
Pro = 1 << 2, // 0100
Ultra = 1 << 3 // 1000
}
If you do not assign numbers it will auto assign them starting at 0 going up by 1 for each option after that (this is standard enum behavior, adding the [Flags] attribute does not change this behavior)
[Flags]
enum Editions
{ //binary format
Educational = 0, // 0000
Basic = 1, // 0001
Pro = 2, // 0010
Ultra = 3 // 0011
}
So the two tests you did was: 0001 has the flag 0000 set (which is true, you are not testing for any flags) and 0000 has the flag 0001 set (which is defiantly false)
However looking at your names I doubt you should be using [Flags] at all because I doubt whatever you are doing can be Basic and be Pro at the same time. If you are trying to use flags to make testing enum values easier just use a switch statement instead
Editions edition = GetEdition();
switch(edition)
{
case Editions.Basic:
DoSomthingSpecialForBasic();
break;
case Editions.Pro:
case Editions.Ultra:
DoSomthingSpecialForProAndUltra();
break;
//Does not do anything if Editions.Educational
}

Working out Enum masks c#

I was wondering how the following enum masking works
If I have an Enum structure
public enum DelMask
{
pass = 1,
fail = 2,
abandoned = 4,
distinction = 8,
merit = 16,
defer = 32,
}
I have seen the following code
int pass = 48;
if ((pass & (int)DelMask.defer) > 0)
//Do something
else if ((pass & (int)DelMask.merit ) > 0)
//Do something else
I am wondering can anyone help me figure out how which block will get executed?
Basic bit logic at work here. The integer 48 ends like this in binary:
0011 0000
Defer, 32, is:
0010 0000
Merit, 16, is:
0001 0000
Now when you perform a logical AND (&), the resulting bits are set where they are both in the input:
pass & (int)DelMask.defer
0011 0000
0010 0000
========= &
0010 0000
The result will be 16, so ((pass & (int)DelMask.defer) > 0) will evaluate to true. Both if's will evaluate to true in your example because both flags are present in the input. The second one won't be evaluated though, because it's an else if.
Both are correct so the first will get executed.
16 is 10000
32 is 100000
48 is 16+32 so it is 110000
10000 & 110000 is 10000
100000 & 110000 is 100000
Both are bigger than zero.
48 = 16 (merit) + 32 (defer).
Thus pass & (int)DelMask.defer evaluates to 32, so the first block runs.
If that wasn't the case, pass & (int)DelMask.merit evaluates to 16, so the second block would run if it got that far.
This only works because the values in the enum are all different powers of 2 and thus correspond to independent bits in the underlying int. This is what is known as a bit flags enum.
First, it should be int pass = 48;
Basically this code checks whether a bit is set in a binary representation of the number. Each & operation should produce a result with all zeroes and one on the place where it is in the mask. for instance:
48: 110000
defer = 32: 100000
______
& 100000
So you can use this code:
int pass = 48;
if ((pass & (int)DelMask.defer) == (int)DelMask.defer)
//Do something
else if ((pass & (int)DelMask.merit ) == (int)DelMask.merit)
//Do something else
Well you need to think of those numbers as binary. I'll use the d suffix to show decimal notation and b suffix for binary notation.
enum values:
01d = 000001b
02d = 000010b
04d = 000100b
08d = 001000b
16d = 010000b
32d = 100000b
pass value:
48d = 110000b
Now the & is the bit-wise AND operator. Which means that if c = a&b, the nth bit in c will be 1 if and only if the nth bit is 1 in both a and b.
So:
16d & 48d = 010000b = 16d > 0
32d & 48d = 100000b = 32d > 0
As you see, your number 48d "matches" with both 16d and 32d. That is why this kind of enums is generally described as a "flag" enum: you can have with one integer the value of several "flags".
As for your code, the first if operator will be verified, which means that you will enter it and "Do something". You will not "Do something else".
Generally in C#, we use the [Flags] attribute for flag enums, which allows not actually writing the decimal values for the enum members. As usual, the example in the MSDN is useless so I'll refer to this SO question for more details about how to use it (note that to know if a value x has a flag f set, you can either do x & f == f or x | f == x, but the usage seems to be to generally use the latter one).

FlagsAttribute Enum problems

So I'm building an MSNP (windows live messenger) client. And I've got this list of capabilities
public enum UserCapabilities : long
{
None = 0,
MobileOnline = 1 << 0,
MSN8User = 1 << 1,
RendersGif = 1 << 2,
....
MsgrVersion7 = 1 << 30,
MsgrVersion8 = 1 << 31,
MsgrVersion9 = 1 << 32,
}
full list here http://paste.pocoo.org/show/383240/
The server sends each users capabilities to the client as a long integer, which I take and cast it to UserCapabilities
capabilities = Int64.Parse(e.Command.Args[3]);
user._capabilities = (UserCapabilities)capabilities;
This is fine, and with atleast one user (with a capability value of 1879474220), I can do
Debug.WriteLine(_msgr.GetUser(usr).Capabilities);
and this will output
RendersGif, RendersIsf, SupportsChunking, IsBot, SupportsSChannel, SupportsSipInvite, MsgrVersion5, MsgrVersion6, MsgrVersion7
But with another user, who has the capability value of (3055849760), when I do the same, I just get the same number outputted
3055849760
What I would like to be seeing is a list of capabilities, as it is with the other user.
I'm sure there is a very valid reason for this happening, but no matter how hard I try to phrase the question to Google, I am not finding an answer.
Please help me :)
The definition of the shift operators means that only the 5 least significant bits are used for 32-bit numbers and only the first 6 bits for 64-bit; meaning:
1 << 5
is identical to
1 << 37
(both are 32)
By making it:
MsgrVersion9 = 1L << 32
you make it a 64-bit number, which is why #leppie's fix works; otherwise the << is considered first (and note that 1<<32 is identical to 1<<0, i.e. 1), and then the resulting 1 is converted to a long; so it is still 1.
From ยง14.8 in the ECMA spec:
For the predefined operators, the number of bits to shift is computed as follows:
When the type of x is int or uint, the shift count is given by the low-order five bits of count. In other words, the shift count is computed from count & 0x1F.
When the type of x is long or ulong, the shift count is given by the low-order six bits of count. In other words, the shift count is computed from count & 0x3F.
If the resulting shift count is zero, the shift operators simply return the value of x.
Shift operations never cause overflows and produce the same results in checked and unchecked context
The problem could be with arithmetic overflow.
Specifically at:
MsgrVersion8 = 1 << 31,
MsgrVersion9 = 1 << 32,
I suggest you make it:
MsgrVersion8 = 1L << 31,
MsgrVersion9 = 1L << 32,
To prevent accidental overflow.
Update:
Seems likely as the smaller number on 'touches' 31 bits, while the bigger one 'touches' 32 bits.

Categories