• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            SEMAN

            曾經(jīng)滄海難為水、除卻巫山不是云

            C++博客 首頁 新隨筆 聯(lián)系 聚合 管理
              9 Posts :: 3 Stories :: 24 Comments :: 0 Trackbacks

            Introduction   http://www.codeproject.com/cpp/bitbashing.asp

            I have noticed that some people seem to have problems with bitwise operators, so I decided to write this brief tutorial on how to use them.

            An Introduction to bits

            Bits, what are they you may ask?

            Well, simply put, bits are the individual ones and zeros that make up every thing we do with computers. All the data you use is stored in your computer using bits. A BYTE is made up of eight bits, a WORD is two BYTEs, or sixteen bits. And a DWORD is two WORDS, or thirty two bits.

             0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0
            ||                  |                   |                    |                  ||
            |+- bit 31       |                    |                    |         bit 0 -+|
            |                   |                    |                    |                   |
            +-- BYTE 3 ---+--- BYTE 2 ---+--- BYTE 1 ---+-- BYTE 0 ---+
            |                                        |                                         |
            +----------- WORD 1 --------+----------- WORD 0 ---------+
            |                                                                                  |
            +--------------------------- DWORD -----------------------+
            

            The beauty of having bitwise operators is that you can use a BYTE, WORD or DWORD as a small array or structure. Using bitwise operators you can check or set the values of individual bits or even a group of bits.

            Hexadecimal numbers and how they relate to bits

            When working with bits, it is kind of hard to express every number using just ones and zeros, which is known as binary notation. To get around this we use hexadecimal (base 16) numbers.

            As you may or may not know, it takes four bits to cover all the numbers from zero to fifteen, which also happens to be the range of a single digit hexadecimal number. This group of four bits, or half a BYTE, is called a nibble. As there are two nibbles in a BYTE, we can use two hexadecimal digits to show the value of one BYTE.

            NIBBLE   HEX VALUE
            ======   =========
             0000        0
             0001        1
             0010        2
             0011        3
             0100        4
             0101        5
             0110        6
             0111        7
             1000        8
             1001        9
             1010        A
             1011        B
             1100        C
             1101        D
             1110        E
             1111        F

            So if we had one BYTE containing the letter 'r' (ASCII code 114) it would look like this:

            0111 0010    binary
              7    2     hexadecimal

            We could write it as '0x72'

            Bitwise operators

            There are six bitwise operators. They are:
               &   The AND operator
               |   The OR operator
               ^   The XOR operator
               ~   The Ones Complement or Inversion operator
              >>   The Right Shift operator
              <<   The Left Shift operator.

            The & operator

            The & (AND) operator compares two values, and returns a value that has its bits set if, and only if, the two values being compared both have their corresponding bits set. The bits are compared using the following table

               1   &   1   ==   1
               1   &   0   ==   0
               0   &   1   ==   0
               0   &   0   ==   0

            An ideal use for this is to set up a mask to check the values of certain bits. Say we have a BYTE that contains some bit flags, and we want to check if bit four bit is set.

            BYTE b = 50;
            if ( b & 0x10 )
                cout << "Bit four is set" << endl;
            else
                cout << "Bit four is clear" << endl;

            This would result in the following calculation

                00110010  - b
             & 00010000  - & 0x10
              ----------
                00010000  - result

            So we see that bit four is set.

            The | operator

            The | (OR) operator compares two values, and returns a value that has its bits set if one or the other values, or both, have their corresponding bits set. The bits are compared using the following table

               1   |   1   ==   1
               1   |   0   ==   1
               0   |   1   ==   1
               0   |   0   ==   0

            An ideal use for this is to ensure that certain bits are set. Say we want to ensure that bit three of some value is set

            BYTE b = 50;
            BYTE c = b | 0x04;
            cout << "c = " << c << endl;

            This would result in the following calculation

                00110010  - b
              | 00000100  - | 0x04
              ----------
                00110110  - result

            The ^ operator

            The ^ (XOR) operator compares two values, and returns a value that has its bits set if one or the other value has its corresponding bits set, but not both. The bits are compared using the following table

               1   ^   1   ==   0
               1   ^   0   ==   1
               0   ^   1   ==   1
               0   ^   0   ==   0

            An ideal use for this is to toggle certain bits. Say we want toggle the bits three and four

            BYTE b = 50;
            cout << "b = " << b << endl;
            b = b ^ 0x18;
            cout << "b = " << b << endl;
            b = b ^ 0x18;
            cout << "b = " << b << endl;

            This would result in the following calculations

                00110010  - b
             ^ 00011000  - ^ 0x18
              ----------
                00101010  - result
            
                00101010  - b
            ^ 00011000 - ^ 0x18 ---------- 00110010 - result

            The ~ operator

            The ~ (Ones Complement or inversion) operator acts only on one value and it inverts it, turning all the ones int zeros, and all the zeros into ones. An ideal use of this would be to set certain bytes to zero, and ensuring all other bytes are set to one, regardless of the size of the data. Say we want to set all the bits to one except bits zero and one

            BYTE b = ~0x03;
            cout << "b = " << b << endl;
            WORD w = ~0x03;
            cout << "w = " << w << endl;

            This would result in the following calculations

                00000011  - 0x03
                11111100  - ~0x03  b
            
                0000000000000011  - 0x03
                1111111111111100  - ~0x03  w

            Another ideal use, is to combine it with the & operator to ensure that certain bits are set to zero. Say we want to clear bit four

            BYTE b = 50;
            cout << "b = " << b << endl;
            BYTE c = b & ~0x10;
            cout << "c = " << c << endl;

            This would result in the following calculations

                00110010  - b
             & 11101111  - ~0x10
              ----------
                00100010  - result

            The >> and << operators

            The >> (Right shift) and << (left shift) operators move the bits the number of bit positions specified. The >> operator shifts the bits from the high bit to the low bit. The << operator shifts the bits from the low bit to the high bit. One use for these operators is to align the bits for whatever reason (check out the MAKEWPARAM, HIWORD, and LOWORD macros)

            BYTE b = 12;
            cout << "b = " << b << endl;
            BYTE c = b << 2;
            cout << "c = " << c << endl;
            c = b >> 2;
            cout << "c = " << c << endl;

            This would result in the following calculations

                00001100  - b
                00110000  - b << 2
                00000011  - b >> 2

            Bit Fields

            Another interesting thing that can be done using bits is to have bit fields. With bit fields you can set up minature structures within a BYTE, WORD or DWORD. Say, for example, we want to keep track of dates, but we want to use the least amount of memory as possible. We could declare our structure this way

            struct date_struct {
                BYTE day   : 5,   // 1 to 31
                     month : 4,   // 1 to 12
                     year  : 14;  // 0 to 9999
                } date;

            In this example, the day field takes up the lowest 5 bits, month the next four, and year the next 14 bits. So we can store the date structure in twenty three bits, which is contained in three BYTEs. The twenty fourth bit is ignored. If I had declared it using an integer for each field, the structure would have taken up 12 BYTEs.

            |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|
               |                                   |          |           |
               +------ year -------------+ month + day --+

            Now lets pick this declaration apart to see what we are doing.

            First we will look at the data type we are using for the bit field structure. In this case we used a BYTE. A BYTE is 8 bits, and by using it, the compiler will allocate one BYTE for storage. If however, we use more than 8 bits in our structure, the compiler will allocate another BYTE, as many BYTEs as it takes to hold our structure. If we had used a WORD or DWORD, the compiler would have allocated a total of 32 bits to hold our structure.

            Now lets look at how the various fields are declared. First we have the variable (day, month, and year), followed by a colon that separates the variable from the number of bits that it contains. Each bit field is separated by a comma, and the list is ended with a semicolon.

            Now we get to the struct declaration. We put the bit fields into a struct like this so that we can use convention structure accessing notation to get at the structure members. Also, since we can not get the addresses of bit fields, we can now use the address of the structure.

            date.day = 12;
            
            dateptr = &date;
            dateptr->year = 1852;


            posted on 2005-11-21 08:03 味全每日C++ 閱讀(794) 評論(0)  編輯 收藏 引用

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            久久国产色av免费看| 99久久精品免费看国产免费| 青青青青久久精品国产h| 人妻精品久久无码区| 色综合久久久久久久久五月| 久久亚洲精品无码aⅴ大香| 香蕉久久永久视频| 热99RE久久精品这里都是精品免费| 亚洲午夜精品久久久久久app| 久久人人爽人人爽人人片AV麻豆 | 欧美黑人又粗又大久久久| 久久久这里有精品| 久久午夜羞羞影院免费观看| 久久久久亚洲AV无码麻豆| 久久久久女人精品毛片| 91精品国产综合久久精品| 国产成人精品久久一区二区三区av| 国产精品va久久久久久久| 久久毛片一区二区| 97久久精品人妻人人搡人人玩| 91亚洲国产成人久久精品| 久久久久久久久久免免费精品 | 囯产极品美女高潮无套久久久| 久久久久久人妻无码| 久久99精品国产麻豆蜜芽| 久久这里只精品99re66| 久久香蕉超碰97国产精品| 久久99精品久久久久久噜噜| 久久天天躁狠狠躁夜夜躁2014| 韩国免费A级毛片久久| 久久国产午夜精品一区二区三区| 久久青青色综合| 国产成人无码精品久久久免费| 国产精品久久久久蜜芽| 久久久久久免费一区二区三区| 亚洲乱码日产精品a级毛片久久 | 国产亚洲精久久久久久无码| 一本久久免费视频| 色综合久久最新中文字幕| 亚洲国产精品无码久久久蜜芽| 久久精品国产亚洲Aⅴ香蕉|