0

数値があり、for ループを使用せずにビット32-bitビットに設定したい。 m n

例えば:

mビットは2ndまたは5thまたは9thまたは10thです。
nbit は 22ndor27または11thbit です。

(m < n) と仮定します。

助けてください。ありがとう

4

1 に答える 1

12

ビットが LSB から MSB に番号付けされているとします。

BIT NUMBER    31                                     0
               ▼                                     ▼
number bits    0000 0000 0000 0000 0000 0000 0001 0101 
               ▲    ^           ^                    ▲ 
              MSB   |           |                   LSB
                    |           | 
                   n=27        m=17

LSB - Least Significant Bit (numbered 0)
MSB - Most  Significant Bit (numbered 31) 

上の図では、ビットが LSB から MSB までどのように番号付けされているかを示しています。nmwhereの相対位置に注意してくださいn > m


n から m までのビット (すべて 1) を設定するには


1位置mからn(where n > m) までのすべてのビットを 32 ビットの数値に設定します。1すべてのビットが~nm、残りのビットがである 32 ビットのマスクが必要です0

たとえば、 から までのすべてのビットを設定するm=17には、n=27次のようなマスクが必要です。

BIT NUMBER    31   n=27        m=17                  0
               ▼    ▼           ▼                    ▼
mask =         0000 1111 1111 1110 0000 0000 0000 0000

また、32 ビットの数値がある場合、ビット単位の OR ( |) とこの数値を使用して、 からまで1のすべてのビットを設定できます。他のすべてのビットは変更されません。mn

ORは次のように機能します。

x | 1 = 1   , and 
x | 0 = x 

ここで、 x値は または のいずれ10です。

したがって、次のようにします。

 num32bit = num32bit | mask; 

ビットに設定できn、残りのビットは変更されません。たとえば、= 、m1num32bit0011 1001 1000 0000 0111 1001 0010 1101

それから:

0011 1001 1000 0000 0111 1001 0010 1101   <--- num32bit
0000 1111 1111 1110 0000 0000 0000 0000   <--- mask     
----------------------------------------  ---------------Bitwise OR operation  
0011 1111 1111 1110 0111 1001 0010 1101   <--- new number  
---- ▲           ▲  -------------------
     |-----------|   this bits are from `num32bit`
      all bits are   
      1 here

これが私が意味することです:

     num32bit = num32bit | mask; 

##マスクの作り方は?

すべてのビットが1からnmその他がであるマスクを作成するには0、次の 3 つの手順が必要です。

  1. Create mask_n: から右側のすべてのビットn=27が 1

     BIT NUMBER     31  n=27                              0
                    ▼    ▼                                ▼
     mask_27=       0000 1111 1111 1111 1111 1111 1111 1111
    

    >>プログラミングでは、これは右シフト ( ) 4 回で作成できます。

    そして、なぜ4ですか?

     4 = 32 - n - 1  ==> 31 - 27 ==> 4
    

    また、注意: の補数 ( ~)0はすべてのビットが 1 であり、C では符号なし右シフトが必要です。符号付き右シフトと符号なし右シフトの違いを
    理解してください

  2. Create mask_m: から左側のすべてのビットm=17が 1 です。

     BIT NUMBER    31              m=17                  0
                   ▼                ▼                    ▼
     mask_17       1111 1111 1111 1110 0000 0000 0000 0000
    
  3. Create mask: 上記のビットごとの AND to: mask = mask_n & mask_m:

     mask =         0000 1111 1111 1110 0000 0000 0000 0000
                         ▲           ▲
     BIT NUMBER          27          17
    

そして、以下は、getMask(n, m)ステップ 3 のマスクのように見える符号なしの数値を返す関数です。

#define BYTE 8
typedef char byte; // Bit_sizeof(char) == BYTE
unsigned getMask(unsigned n,
              unsigned m){
    byte noOfBits = sizeof(unsigned) * BYTE;
    unsigned mask_n = ((unsigned)~0u) >> (noOfBits - n - 1),
             mask_m = (~0u) << (noOfBits - m),
             mask = mask_n & mask_m; // bitwise & of 2 sub masks
    return mask;
}

私をテストするために、指定された数値をバイナリ形式で出力する関数と binary() 関数getMask()も作成しました。main()

void binary(unsigned);
int main(){
    unsigned num32bit = 964720941u;
    unsigned mask = 0u;
    unsigned rsult32bit;
    int i = 51;     
    mask = getMask(27, 17);
    rsult32bit  = num32bit | mask;  //set n to m bits 1
    printf("\nSize of int is = %ld bits, and " 
           "Size of unsigned = %ld e.g.\n", sizeof(int) * BYTE,
                                            sizeof(unsigned) * BYTE);
    printf("dec= %-4u, bin= ", 21);
    binary(21);
    printf("\n\n%s %d\n\t   ", "num32bit =", num32bit); 
    binary(num32bit);
    printf("mask\t   "); 
    binary(mask);
    while(i--) printf("-");
    printf("\n\t   "); 
    binary(rsult32bit);
    printf("\n");
    return EXIT_SUCCESS;
}
void binary(unsigned dec){
  int i = 0,
      left = sizeof(unsigned) * BYTE - 1;
  for(i = 0; left >= 0; left--, i++){
    printf("%d", !!(dec & ( 1 << left )));
    if(!((i + 1) % 4)) printf(" ");
  }
  printf("\n");
}  

このテスト コードは次のように実行されます (出力は上記の例で説明したものとまったく同じです)。

Output of code: 
-----------------
$ gcc b.c 
:~$ ./a.out 

Size of int is = 32 bits, and Size of unsigned = 32 e.g.
dec= 21  , bin= 0000 0000 0000 0000 0000 0000 0001 0101 

num32bit = 964720941
           0011 1001 1000 0000 0111 1001 0010 1101 
mask       0000 1111 1111 1110 0000 0000 0000 0000 
---------------------------------------------------
           0011 1111 1111 1110 0111 1001 0010 1101 
:~$ 

さらに、 getMask()次のように、関数を 2 つのステートメントで短い形式で記述できます。

unsigned getMask(unsigned n,
                 unsigned m){
    byte noOfBits = sizeof(unsigned) * BYTE;
    return ((unsigned)~0u >> (noOfBits - n - 1)) &
           (~0u << (noOfBits -m));
}           

注:コードをクリーンアップするために、冗長な括弧を削除しました。演算子の優先順位を覚える必要はありませんが、 を使用して優先順位をオーバーライドできる()ため、優れたプログラマーは常に優先順位表を参照して適切なコードを記述します。

より良いアプローチは、以下のようにマクロを書くことです:

#define _NO_OF_BITS sizeof(unsigned) * CHAR_BIT
#define MASK(n, m)  (((unsigned)~0u >> (_NO_OF_BITS - n - 1)) & \
                    (~0u << (_NO_OF_BITS - m)))

そして次のように呼び出します:

result32bit  = num32bit | MASK(27, 17);

n から m までのビットをリセット (すべてゼロ) するには


すべてのビットを n から m = 0 にリセットし、残りを変更しない場合は、 の補数 ( ~) が必要ですmask

mask      0000 1111 1111 1111 1000 0000 0000 0000 
~mask     1111 0000 0000 0000 0111 1111 1111 1111   <-- complement 

|また、オペレータの代わりにゼロを設定する&必要があります。

覚えておいて 次のように機能します。

x & 0 = 0   , and 
x & 0 = 0 

ここで、x値は 1 または 0 です。

既にビット単位の補数~演算子 and and &演算子があるため、次の操作を行うだけです。

rsult32bit  = num32bit & ~MASK(27, 17);

そして、それは次のように機能します:

num32bit = 964720941
       0011 1001 1000 0000 0111 1001 0010 1101 
mask   1111 0000 0000 0000 0111 1111 1111 1111 
---------------------------------------------------
       0011 0000 0000 0000 0111 1001 0010 1101 
于 2013-04-10T06:06:16.870 に答える