tags:

views:

168

answers:

3

I need to check if a certain flag is set for an integer.

I already know how to set a flag:

flags := FLAG_A or FLAG_B or FLAG_C

But how can I check if a certain flag is set?

In C++ I used the & operator, but how does that work in Delphi? I'm a bit confused at the moment

+2  A: 

You use the and operator as you would & in C++. On numeric arguments, it's bitwise. Here are some examples of bitwise operations.

T.J. Crowder
But the result of that is again an integer, I require a boolean though :(
Mol
@Mol: Use `<> 0` or `= FLAG_A` to get a boolean, e.g. `if (flags and FLAG_A) <> 0` then the flag is set. If the flag may have more than one bit, use `if (flags and FLAG_A) = FLAG_A` (because the `<> 0` will only test if at least one of the flag's bits are set, not if all of them are).
T.J. Crowder
@Mol, the result is an integer in C++, too. C++ simply provides an automatic conversion from int to bool, whereas Delphi requires you to be explicit about what you mean. The usual way is to compare against zero, but you could also type-cast your result to `LongBool`.
Rob Kennedy
@Mol: If you want a boolean result, check out Serg's answer. Use a set and use "in" to test. Pascal doesn't do the "anything can be a boolean" thing; in fact, most of us see it as a design flaw of C's. In the Pascal family, a boolean is a boolean and a number is a number and they're not the same thing as each other, by design.
Mason Wheeler
+12  A: 

In Delphi you have 2 options:

1) use 'and' operator, like this:

const
  FLAG_A = 1;  // 1 shl 0
  FLAG_B = 2;  // 1 shl 1
  FLAG_C = 4;  // 1 shl 2

var
  Flags: Integer;

[..]
  Flags:= FLAG_A or FLAG_C;
  if FLAG_A and Flags <> 0 then ..  // check FLAG_A is set in flags variable

2) define set type:

type
  TFlag = (FLAG_A, FLAG_B, FLAG_C);
  TFlags = set of TFlag;

var
  Flags: TFlags;

[..]
  Flags:= [FLAG_A, FLAG_C];
  if FLAG_A in Flags then ..  // check FLAG_A is set in flags variable
Serg
+1 for proposing sets.
Ulrich Gerhardt
+1 for reminding me of a disaster that occurred when a smarty-pants developer caused big trouble by essentially testing for: ((FLAG_A and Flags) = 1) instead of ((FLAG_A and Flags) <> 0) It didn't work at all! And he snuck his "performance boost" change into one of the base classes, so we started having subtle data problems throughout the system.
Chris Thornton
A: 

I usually use this function:

// Check if the bit at ABitIndex position is 1 (true) or 0 (false)
function IsBitSet(const AValueToCheck, ABitIndex: Integer): Boolean;
begin
  Result := AValueToCheck and (1 shl ABitIndex) <> 0;
end;

and the setters:

// set the bit at ABitIndex position to 1
function SetBit(const AValueToAlter, ABitIndex: Integer): Integer;
begin
  Result := AValueToAlter or (1 shl ABitIndex);
end;

// set the bit at ABitIndex position to 0
function ResetBit(const AValueToAlter, ABitIndex: Integer): Integer;
begin
  Result := AValueToAlter and (not (1 shl ABitIndex));
end;

Note there is no range checking, just for performance. But easy to add if u need to

DonnVall