Check if flag is set in integer variable

 ̄綄美尐妖づ 提交于 2019-12-08 07:42:48

问题


I am making my own simple drawing engine. I am trying to determine if a variable has been set to a specific value using what I think is called bitwise comparison but I maybe wrong.

I've always been a bit confused about what the following is and how I use it:

int DRAW_REPEAT_X = 70001; // I have a feeling I should make this value binary instead of a unique number, ie, 0
int DRAW_REPEAT_Y = 70002; // I have a feeling I should make this value binary instead of a unique number, ie, 2
int drawMethod    = DRAW_REPEAT_X | DRAW_REPEAT_Y; // this means I want to repeat an image on both the x and y axis doesn't it?

// Now I want to check if drawMethod has DRAW_REPEAT_X set: this is where I struggle to know how to check this
// Is the following correct?
if (drawMethod && DRAW_REPEAT_X) {
  // the user wants me to repeat an image along the x axis
}

// Now I want to check if drawMethod has DRAW_REPEAT_Y set: this is where I struggle to know how to check this
if (drawMethod && DRAW_REPEAT_Y) {
  // the user wants me to repeat an image along the x axis
}

Is the following code correctly checking if DRAW_REPEAT_X is set? It always returns 1 in my anding check.

EDIT And to check whether both bits are set do I do this?

if (drawMethod & DRAW_REPEAT_X & DRAW_REPEAT_Y) {
   // both set
}

// OR

if (drawMethod & DRAW_REPEAT_X && drawMethod & DRAW_REPEAT_Y) {
   // both set
}

回答1:


No it isn't, you should use the bitwise AND operator instead - & and set the flags as binary values - your intuition is correct on that side.

A common trick to setting specific bits is using the shift operator:

int DRAW_REPEAT_X = 0x1 << 0;  //first bit set to 1, others 0
int DRAW_REPEAT_Y = 0x1 << 1;  //second bit set to 1, others 0

and check the int as

if (drawMethod & DRAW_REPEAT_X)  //check it that particular flag is set, ignore others
{
}



回答2:


For this to work, your flag variables each need to have a single, unique bit set. That bit is the "flag". For constants where it's the bitwise representation that matters, it's much more convenient to use hexadecimal or octal (because these bases are a power of 2) than decimal. So, for example:

enum {
    DRAW_REPEAT_X = 0x01,    /* First bit set */
    DRAW_REPEAT_Y = 0x02,    /* Second bit set */
    DRAW_MIRRORED = 0x04,    /* Third bit set */
};

int drawMethod = DRAW_REPEAT_X | DRAW_REPEAT_Y;  /* Will have both first and second bits set */

Then you use bitwise-and & rather than logical-and && to test the bits. a & b will be non-zero if and only if there is at least one bit that is set in both a and b. In the case of testing for a flag, one of these will have only one bit set - the flag you're interested in - so the result of a & flag will be non-zero if and only if the flag is set in a:

if (drawMethod & DRAW_REPEAT_X) {
  // the user wants me to repeat an image along the x axis
}

if (drawMethod & DRAW_REPEAT_Y) {
  // the user wants me to repeat an image along the x axis
}

The hexadecimal pattern for constants with one bit set is 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, ...




回答3:


As it stands right now, you aren't using flags so much as having a value that indicates a method. Much better is to use some sort of bits, like this:

int DRAW_REPEAT_X=0x01;
int DRAW_REPEAT_Y=0x02;

And then check the ifs like you are doing now, but with a single &

if (drawMethod & DRAW_REPEAT_X)

Typically, your integers (DRAW_REPEAT_X) should be public static, if you are working with a class architecture. But not knowing if that is the case, I won't include them




回答4:


Here's a code snippet using the WinAPIs that shows setting two flags to a value, and then checking for the existence of at least one of those flags in that value. It should return 0;

INPUT mip;
mip.type = INPUT_MOUSE;
mip.mi.mouseData = 0;
mip.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;

if (mip.mi.dwFlags & (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_HWHEEL))
    return 0;

If you want to check for an exact value combination, you don't need to use the bitwise operator &, and can do a simple == check.

For example, the updated line near the bottom

INPUT mip;
mip.type = INPUT_MOUSE;
mip.mi.mouseData = 0;
mip.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;

if (mip.mi.dwFlags == (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE))
    return 0;


来源:https://stackoverflow.com/questions/13464063/check-if-flag-is-set-in-integer-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!