问题
I do not understand how flags work and would appreciate some help and a link to a tutorial to try and understand what is happening when adding values to an Integer as flags.
For example, I am backing up various-sized files to an SD card. A lot of the files often already exist, so I first run through and check FileExists
, FileAge
, and size, and if appropriate, add it to the list to copy across with ShFileOperation
. Using a routine by Peter Barlow from here it is working but I want to suppress some things.
If the file is larger than 10M then I want to show the win-progress bar, I do not want a prompt for overwriting an existing file. Plus, I do not want it to check if there is enough room as I will have already done that so I know there is enough room for all the updates.
I have tried messing with AND
and OR
and +
and -
but can't seem to figure out the combination I need.
if aBigFile then
OpStruc.fFlags:=FOF_NOCONFIRMATION or FOF_SIMPLEPROGRESS else
OpStruc.fFlags:=FOF_SILENT or FOF_NOCONFIRMATION;
Could someone please give me an example of what I need to make this work?
回答1:
And
and or
are bitwise operators. That means they apply to each bit of their operands independently. When learning about bitwise operations, it helps to picture the operands in binary rather than decimal. (Once you're familiar with how they work, decimal still isn't the ideal format; most people prefer hexadecimal instead, or, to a lesser extent, octal.)
For and
, the result bit is set if and only if the bits of both operands are set; otherwise, the result is cleared. For or
, the result is set if either one of the operand bits is set. It's also set when both are set, so it's known as inclusive or. (There's also exclusive or, where the result is set only when exactly one of the two operands is set. Delphi uses the xor
operator for that.)
To compute a result for operands that are larger than one bit, the bits are computed in parallel, so the first bit of the result is computed from the first bits of the operands, the second bit from the second bits, and so on.
When combining flags, you use or
to indicate that you want both flags set. For example:
// Indicate we want both a simple progress bar *and* a lack of confirmation.
OpStruc.fFlags := fof_NoConfirmation or fof_SimpleProgress;
The first flag's value in binary is 00010000. The second's is 000100000000. That makes the result 000100010000.
You won't frequently use and
when setting flags. Rather, that's usually used when you want to check whether a flag is set. For example:
// Check whether the no-confirmation flag is set:
var FlagSet: Boolean;
FlagSet := (OpStruc.FFlags and fof_NoConfirmation) = fof_NoConfirmation;
Since the input was 000100010000, the result of the and
with the flag value is 000000010000. That's equal to the flag value, so the value of FlagSet
will be true.
It's sometimes enough to check whether the result of the and
operation is non-zero, rather than to check that it's exactly equal to the flag you were testing. When the flag consists of multiple set bits, you want to check that all of them were present, though. If only one were present, the result of the and
operation would still be non-zero.
To remove flags, you use not
to invert the bits of the flag you want to remove (clearing all the set bits and vice versa), and then use and
to clear those bits. For example:
OpStruc.FFlags := OpStruc.FFlags and not fof_SimpleProgress;
The inverse of fof_SimpleProgress
is 111011111111. The value of FFlags
so far is 000100010000. Combining those with and
will yield 000000010000, which equals fof_NoConfirmation
, just as we'd expect by removing fof_SimpleProgress
.
Now that you understand how individual flag values get combined, you're equipped indicate which flags you want to pass to the particular API function you're having trouble with. Read the documentation for each flag and decide whether it's one you want to use. If it is, include it in your list of flags.
You can combine flags with or
in any order. If you know you always want certain flags, and you conditionally want others, you can start with your list of common flags and then add others later. For example:
OpStruc.FFlags := fof_NoConfirmation or fof_SimpleProgress;
if BigFiles then
OpStruct.FFlags := OpStruc.FFlags or fof_Silent;
It will frequently work to use addition to combine flags. Obviously, the result of fof_NoConfirmation or fof_SimpleProgress
is equal to fof_NoConfirmation + fof_SimpleProgress
. However, that only works when the bit values of each flag are distinct, and when no flag is included more than once. The result of fof_Silent or fof_Silent
is equal to fof_Silent
, whereas the result of fof_Silent + fof_Silent
is fof_RenameOnCollision
, which is an entirely unrelated flag. Always use and
and or
when working with flags, never +
and -
.
来源:https://stackoverflow.com/questions/22440473/how-do-integer-flags-work