私は次のコード行を見ました here C.
int mask = ~0;
CおよびC++でmask
の値を出力しました。常に-1
を出力します。
だから私はいくつかの質問があります:
~0
をmask変数に割り当てるのですか?~0
の目的は何ですか?-1
の代わりに~0
を使用できますか?これは、現在のアーキテクチャで整数に含まれるビット数を知る必要なく、整数のすべてのバイナリビットを1ビットに設定するポータブルな方法です。
CおよびC++では、符号の大きさ、1の補数、2の補数の3つの異なる符号付き整数形式を使用できます。
~0
は、符号形式に関係なく、すべて1ビットのを生成しますシステムが使用します。 ポータブル-1
より
U
接尾辞(つまり、-1U
)を追加して、オールワンビットパターンportablyを生成できます。1。ただし、~0
意図をより明確に示す:値0のすべてのビットを反転します。一方、-1は、バイナリ表現ではなく、マイナス1の値が必要であることを示します
1 符号なしの演算は常に 結果の型で表現できる最大値よりも1大きい数を法とする縮小
2の補数プラットフォーム(想定)で-1が得られますが、-1を直接書き込むことは規則(整数0..255、単項!
、~
およびバイナリ&
、^
、|
、+
、<<
および>>
は許可されます)。
特定のタスクを実行するために、演算子と言語構成にいくつかの制限があるコーディングの課題を勉強しています。
最初の問題は、-
演算子を使用せずに値-1を返すです。
2の補数で負の数を表すマシンでは、値-1
はすべてのビットが1
に設定されて表されるため、~0
は-1
に評価されます。
/*
* minusOne - return a value of -1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 2
* Rating: 1
*/
int minusOne(void) {
// ~0 = 111...111 = -1
return ~0;
}
ファイル内の他の問題は、常に正しく実装されていません。 2番目の問題は、int
値が16ビット符号付きshort
に収まるという事実を表すブール値を返すことです:
/*
* fitsShort - return 1 if x can be represented as a
* 16-bit, two's complement integer.
* Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 1
*/
int fitsShort(int x) {
/*
* after left shift 16 and right shift 16, the left 16 of x is 00000..00 or 111...1111
* so after shift, if x remains the same, then it means that x can be represent as 16-bit
*/
return !(((x << 16) >> 16) ^ x);
}
負の値またはシフト値がint
の範囲を超える数値を左にシフトすると動作が未定義になり、負の値を右にシフトすると実装定義になるため、上記のソリューションは正しくありません(おそらく予想されるソリューションです) 。
これは、1K ZX 80やZX 81コンピューターなどの非常に限られた機器でメモリを節約する方法でした。 BASICでは、あなたは
Let X = NOT PI
のではなく
LET X = 0
数値は4バイトの浮動小数点として格納されているため、後者は最初のNOT PIの代替よりも2バイト多く、NOTとPIのそれぞれが1バイトを使用します。
すべてのコンピューターアーキテクチャで数字をエンコードする方法は複数あります。 2の補数を使用する場合、これは常にtrue:~0 == -1
になります。一方、一部のコンピューターは、~0 == -0
であるため、上記の例が当てはまらない負の数のエンコードに1の補数を使用します。うん、1の補数には負のゼロがあり、それが非常に直感的でない理由です。
あなたの質問に
mask & sth == sth
になります。私個人の考え-コードをできるだけプラットフォームに依存しないようにします。コストは比較的小さく、コードはフェイルプルーフになります