大規模な割り当てを作成するとき、&0xffの動作は常に疑問視されていました。
バイト[i]は8ビットバイナリであり、8ビットバイナリに変換された0xffは11111111なので、バイト[i]と0xffはまだバイト[i]自体ではないですか?
冗談ですか?
この問題について、私はオンラインでのデモが非常に興味深いことを知りました。
#include<stdio.h>
int main(void)
{
char byte = -127;
int a;
a = byte;
printf("%d\n", a);
a = byte & 0xff;
printf("%d", a);
return 0;
}
しかし〜
物事は面白くなり始めました...
&0xffを追加するのはなぜ間違っているのですか?
最初に補完の概念を確認しましょう:
正の数(00000001)の元のコードの場合、最初のビットは符号ビットを表し、逆数と補数は両方ともそれ自体です。
負の数の元のコード(100000001)の場合、逆符号は、符号ビットを除く元の符号の逆演算です。 (111111110)次に+1演算を実行します(すなわち(111111111)
次に、シンボル拡張の概念を紹介します。
8ビットの2進数を例にとると、符号拡張とは、現在の値を変更せずに、それらを16ビットおよび32ビットの2進数に変換することを指します。規則は、それが正の数であるか、補数で表される負の数であるかにかかわらず、必要なことは、上位ビットに符号ビットの値(0または1)を入力することだけです。
トピックを入力してください:
-127がバイトに割り当てられている場合、バイトはchar型であり、そのコンピューターの補数は10000001(8ビット)です[コンピューターでは、負の数は補数の形式で格納されます]。
a = byte;//-127
最初にバイトがint型としてコンソールに出力されたとき、コンパイラーは符号拡張プロセスを行いました。int型は32ビットの2進数であるため、バイト拡張の補数は1111111111111111111111111 10000001(32ビット)です。 32ビットの2の補数で表される10進数も-127です。これは、符号拡張が対応する10進数の現在の値に影響を与えないことを意味します。
これは非常に優れた特性ですが、char型をint型に変換する場合、目的は対応する10進数の不変性を保証することだけではありません。たとえば、今回の大きな仕事は、4つの文字型を1つのint型に変換することです。これは、2の補数の一貫性を保証する必要があります。つまり、4つの文字型に対応するバイナリ01シーケンスはそのままです。 int型の4バイトのバイナリシーケンスとして(8ビットの上位8ビットと下位8ビット)。
a = byte & 0xff;//129
では、2回目に値を割り当てるときになぜ値を変更するのでしょうか。
詳細に分析してみましょう。
シンボル拡張の概念を導入する前に、バイト(10000001)がintに変換されると、上位24ビットは必然的に1で埋められます。このようにして、その2つの補数は実際に変更されました。&0xff(11111111)はバイトをintに変更できますが、上位24ビットは0に設定され、下位8ビットはそのまま残ります。
それから、何人かの学生は疑問に思うかもしれません:0xffである24ビットが1と同じ高さでないのはなぜですか?これは、0xffまたは0xFF自体が32ビット長のintリテラル定数であるため、符号拡張されないためです。
もちろん、2の補数の一貫性を確保したい場合、2進数に対応する10進数は自然に変化します。両方を持つことは不可能です〜
コードの特定の実装を見てみましょう:
a = byte & 0xff;//129
バイト&0xff = 111111111111111111111111110000001&11111111
= 000000000000000000000000 10000001
2進数の重みは129です。
これは、&0xffを追加するとエラーが発生する理由の良い説明です。
この時点でのプログラムは、対応する10進数の整合性ではなく、2の補数の整合性を保証するためです。
最後
大きなジョブの変換アルゴリズムの問題に戻りましょう。2の補数の整合性を確保したいので、最初にバイトに対して&0xff演算を実行する必要があります。もちろん、バイトの符号ビットが0の場合、&0xffは意味がありません。しかし、バイトの符号ビットが1の場合は、最終的に値との論理OR演算を実行するため、それを比較検討する必要があります(たぶん、取得するために努力してきたバイナリシーケンスはすべて1になります)。 )!!