Bitwise operations in C/C ++

Source: Internet
Author: User
Tags bitset

C/C ++ supports low-level bitwise operations, which are well known. Every C/C ++ textbook will talk about this part, but it is very simple. I think many people do not know where bitwise operations are used. This post briefly describes the usefulness of bitwise operations, and further uses require your own experience. It mainly refers to the operation flag value.

/*************************************** */

# Define bti_msk (BIT) (1 <(BIT ))
# Define bit_set (x, bit) (x) | = bti_msk (BIT ))
# Define bit_clr (x, bit) (x) & = ~ Bti_msk (BIT ))
# Define bit_tst (x, bit) (x) & bti_msk (BIT ))

/*************************************** */

Consider that one thing, one system, or one program may have one or more States. To make different behaviors in different states, you can set up some flag values and then make judgments based on the flag values. For example, in the file stream of C ++, you can set some flag values, such as IOS: app, IOS: ate, IOS: binary, IOS: In, IOS :: out, IOS: trunc, and can be used together to create an appropriate file stream. You may define these flag values as the bool type. However, if you set more than one flag value, it will be a waste of space.

For example, if an integer value is defined, unsigned int flags; in the current system, flags should be 32-bit, with 1, 2, 3 .... 32. When bit 1 is set to 1, it indicates that the file is opened in Read mode. When bit 2 is set to 1, indicates opening the file in write mode. When the value of 3 is 1, the file is opened in binary mode .... because flags has 32 bits, you can set 32 different status values, which is also equivalent to 32 bool types. On the one hand, this saves space, and on the other hand, it also has another advantage, that is, as mentioned above, the flag value can be combined.
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>

Well, the above is a bit ambiguous. Next, let's take a look at how to operate these flag values.
Suppose C ++ class IOS is defined like this. In fact, there is no such class, only the ios_basic class, typedef basic_ios <char> Ios;

Class IOS
{
Public:
Enum {APP = 0x0001, ate = 0x0002, binary = 0x0004,
In = 0x0008, out = 0x0010, trunc = 0x0020 };
....
PRIVATE:
Unsigned int flags;
};

Note that in the preceding Enum statement, each value has only one digit and the remaining value is 0. This is very important. You can convert it into a binary format.

Now set the corresponding flags bit to 1. You can do this for flags | = app. This is equivalent to flags = flags | app. Why? In the app, only one digit is 1, and the remaining digits are 0, because 0 | 1 = 0, 0 | 0 = 0, so that the corresponding digits of 0 are unchanged. And 1 | 1 = 1, 1 | 0 = 1, the corresponding bit of 1 must be 1 no matter what the original status is. If you want to set a few bits to 1, you can do this in flags | = (APP | ate | binary ). Because each Enum constant has one digit for one and three digits for one after the operation, as shown in the preceding analysis, the three digits can be set to 1, and the other digits remain unchanged. This is why the logo can be combined. It can also be combined with + because (the number below is in binary format) 0001 + 0010 + 0100 = 0111 is the same as the calculation result. However, we do not advocate the use of +. If I accidentally write an additional flag value (APP | ate | binary), the result is still correct, if + is used, carry is generated and the result is incorrect. Generally, we do not know how many flag values have been combined, so it is safe to use or.

Set the bit corresponding to flags to 0. You can do this to flags & = ~ App. Equivalent to flags = flags &(~ APP ). after the app is reversed, only one bit is 0, and the other is 1. After calculation, the bit corresponding to 1 does not change, and 0 corresponds to no matter whether the original value is 1 or 0, all are set to 0, so that the corresponding bit is set to 0. You can set several flag bits at the same time. Flags & = ~ (APP | ate | binary ).

Now we can change the bit corresponding to flags to 0 if it is 1 and 1 if it is 0. We can do this with flags ^ = app. You can set several flags to flags ^ = (APP | ate | binary ). No more analysis, or it will be too long. For example, if you look at the ASCII table, you will find that the corresponding uppercase and lowercase letters differ by 6th digits. You can use this function to convert uppercase letters to lowercase letters and lowercase letters to uppercase letters.
Void xchgupplow (string & letters)
{
Const unsigned int mask = (1 <5 );

For (size_t I = 0; I <letters. Length (); I ++)
Letters [I] ^ = mask;
}
The premise is that the input string must be full of letters, but to be an operation letter, you can add a judgment based on the original.

Okay, now we can set the corresponding bit value of flags. What if it is determined? If (flags & App) can be written in this way to determine whether the corresponding bit value is 1, because it is true that the C/C ++ language is not 0. Only one digit in the app is 1, and the other digit is 0. If the corresponding digit of flags is also 0, the result 0 is obtained under the same operation. Otherwise, the result is not 0, in this way, you can determine the flag space.

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>
The operation on the flag value above is complete. In fact, a bitset already exists in C ++, and there is no need to perform low-level bitwise operations on its own. The above four operations are called set, reset, flip, and test in bitset. However, in C, such code is still very common, and there is no harm in knowing more points.

If you use a Windows API for programming, you will often encounter such a flag value. to combine them, you can use | or + (only recommended | For the reason described above ). its flag value is also defined in this way, but # define is used.
# Define ws_border 0x0001
# Define ws_caption 0x0002
......
At the beginning, I just couldn't figure out why I could use | or use + for combination. Now I know.

(Note: The number shown above is made by myself. It doesn't matter how to define it. Just make sure that only one digit is 1 and the other is 0. because the constant value is used during programming, no one is so stupid to directly use the value)

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>
In fact, bitwise operations have a lot to do. For example, shift is equivalent to the power of multiplication and division 2 (but the compiler usually optimizes the power of multiplication and division 2 to the shift instruction of assembly, so there is no need to sell it like this. There are two groups of assembly shift commands for signed and unsigned, respectively. I guess the same shift operation in C/C ++ is different for signed and unsigned integers, it will be compiled into different assembly shift commands according to the situation, but it has not been confirmed). In fact, the most useful part of the shift is to construct a mask, for example, the above mask = (1 <5 );

There is also an operation that can be used to calculate the remainder. For example, value & (1 <4-1) is equivalent to converting the high value of value to 0, and the effect is equal to value % 8.

It is also worth mentioning that the ^ operation has a special nature. For example, if a ^ = B is changed to another number, then execute a ^ = B and change it back to the original number. If you do not believe it, you can list the truth table or simplify the logic. Due to this nature, ^ has many uses. For example, if you regard the original text as a and use the same B-or-once, it is equivalent to encryption, followed by B-or-once, which is equivalent to decryption. However, this is very easy to crack. If a B is not enough, you can add a C, such as a ^ = B, a ^ = C, a ^ = C, a ^ = B, and restore the original state.

The following small program exchanges two numbers with an exception or an exception.
Int x = 3;
Int y = 4;

X ^ = y;
Y ^ = X;
X ^ = y;

In fact, even exchange objects can exchange numbers.
Template <typename T>
Void swap (T & obj1, T & obj2)
{
Const int sizeofobj = sizeof (t );
Char * pt1 = (char *) & obj1;
Char * pt2 = (char *) & obj2;

For (size_t I = 0; I <sizeofobj; I ++)
{
Pt1 [I] ^ = pt2 [I];
Pt2 [I] ^ = pt1 [I];
Pt1 [I] ^ = pt2 [I];
}
}

There are also exclusive or operations that can be used in image grating operations. We know that the color is also represented in binary. Different bitwise operations can be performed on the color to obtain different grating values. Because of the special nature of the exclusive or operator, we drew a secondary image with the exclusive or operator raster, and then painted it again in the original place. This can be used to display animations without saving the original profile information. I used to write a two-person greedy snake and used an exclusive or raster. Because the background color is white, that is, full 1, for a ^ 1 = A, so use the paint brush to draw a set color once, and then draw it again to restore. The most interesting thing is that when the two snakes are at the intersection, the color will also be different or superimposed, and a new color will be generated, and the color will be automatically restored when it leaves.
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>
Okay, it's long enough. Stop it. Finally, I will give you a piece of code to check the bit value of the object in the memory. You can check it out.
String bitsofuchar (unsigned char C)
{
Const int numofbitsinuchar = 8;
Unsigned int mask = (1 <7 );
String result (8, '0 ');

For (size_t I = 0; I <numofbitsinuchar; I ++)
{
If (mask & C)
Result [I] = '1 ';

Mask> = 1;
}

Return result;
}

Template <typename T>
String bitsinmemory (const T & OBJ)
{
Int sizeofobj = sizeof (OBJ );
Unsigned char * PT = (unsigned char *) & OBJ;
String result;

For (size_t I = 0; I <sizeofobj; I ++)
{
Result + = bitsofuchar (PT [I]);
Result + = '';
}

Return result;
}

For example, bitsinmemory (12) will output 00001100 00000000 00000000 00000000, And I will know that my machine is in a small tail order.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.