开发者

In C how do I "reverse" this operator |=

I'm new to programming in C and I have the following situation where I know what needs to be done, I'm just not sure of the right way to do. I'll try to keep it as simple as possible, and please let me know if I'm not providing enough info.

There's a .h file with this line:

#define NS_CONN_ENTITYTOOLARGE    0x2000

Then in the C code we have the following flag being set:

connPtr->flags |= NS_CONN_ENTITYTOOLARGE;

Then later on this test:

if (connPtr->flags & NS_CONN_ENTITYTOOLARGE) {
}

Now what I want to do is basically "undo" the flag NS_CONN_ENTITYTOOLARGE. After some Googling I discovered that |= is a "bitwise OR", but I don't feel a lot more enlightened after learning that. Do I need to do a bitwise XOR, a NOT or what?

Here are all the possible values for flags that I can find in the header file.

#define NS_CONN_CLOSED        0x1
#define NS_CONN_SKIPHDRS      0x2
#define NS_CONN_SKIPBODY      0x4
#define NS_CONN_READHDRS      0x8
#define NS_CONN_SENTHDRS      0x10
#def开发者_Python百科ine NS_CONN_KEEPALIVE     0x20
#define NS_CONN_WRITE_ENCODED     0x40
#define NS_CONN_FILECONTENT       0x80
#define NS_CONN_RUNNING           0x100
#define NS_CONN_OVERFLOW      0x200
#define NS_CONN_TIMEOUT           0x400
#define NS_CONN_GZIP          0x800
#define NS_CONN_CHUNK         0x1000
#define NS_CONN_ENTITYTOOLARGE    0x2000


You cannot reverse an OR to the previous value. Information is lost, consider this truth table:

A|B|OR
------
0|0|0
0|1|1
1|0|1
1|1|1

As you can see, information is lost because there are no distinct values for when A were 0 or 1.

What you want to know is how to remove a flag. This can be done by AND'ing with the inverse of the flag:

connPtr->flags &= ~NS_CONN_ENTITYTOOLARGE; 


connPtr->flags &= ~NS_CONN_ENTITYTOOLARGE;

This doesn't exactly "undo" |= because it may have been a no-op for some or all of the bits in NS_CONN_ENTITYTOOLARGE, if they were already in the variable. In these case, those bits will be cleared too regardless of whether they were there in the first place.


A XOR:

connPtr->flags ^= NS_CONN_ENTITYTOOLARGE

Of course, that's considering (say):

  1. flags = 01001101
  2. NS_CONN = 00010000

Example:

flags |= NS_CONN;

OR 01001101
   00010000
------------
   01011101

And then:

flags ^= NS_CONN

XOR 01011101
    00010000
-------------
    01001101 (== original flags)


You need to do a bitwise and with the inverse of the flag:

connPtr->flags &= ~NS_CONN_ENTITYTOOLARGE;

Every bit of ~NS_CONN_ENTITYTOOLARGE is 1 except for the bit that it represents.
Thus, every other bit of the value gets ANDed with 1, which does nothing.


You can't undo it per se - after the operation, connPtr->flags will have a 1 bit in all positions where NS_CONN_ENTITYTOOLARGE had a 1 bit (which is only one position in this case), and it is impossible to know what the original bit values there unless you have actually stored the original value of connPtr->flags somewhere. If you are interested in turning changing the bit position(s) to 0 (which may not have been the original bit value), you can do as the other posts here say.


To remove the flag, you use AND:

connPtr->flags &= ~NS_CONN_ENTITYTOOLARGE;

This will take all the bits in the flags except NS_CONN_ENTITYTOOLARGE.


You want to use connPtr->flags &= ~NS_CONN_ENTITYTOOLARGE where & is AND and ~ is NOT.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜