私はビット演算子の章を読んでいて、1の補数演算子プログラムに出会い、Visual C++で実行することにしました。
int main ()
{
unsigned char c = 4, d;
d = ~c;
printf("%d\n", d);
}
有効な出力が得られます:251
次に、d
を変数として使用して~c
の値を保持する代わりに、~c
の値を直接出力することにしました。
int main ()
{
unsigned char c=4;
printf("%d\n", ~c);
}
出力は-5
になります。
なぜうまくいかなかったのですか?
char
は、2番目のスニペットの操作~
の前にint
ステートメントでprintf
に昇格されます。つまり、c
、つまり
0000 0100 (2's complement)
バイナリで昇格(32ビットマシンを想定)
0000 0000 0000 0000 0000 0000 0000 0100 // Say it is x
そのビット単位の補数は、値の2の補数から1を引いたものに等しい(~x = −x − 1
)
1111 1111 1111 1111 1111 1111 1111 1011
これは、2の補数形式の10進数の-5
です。
char
c
からint
へのデフォルトの昇格は、
d = ~c;
補数演算の前ですが、d
はunsigned char
型であるため、結果はunsigned char
に変換されます。
単純な代入(
=
)では、右のオペランドの値が代入式の型に変換され、左のオペランドで指定されたオブジェクトに格納されている値を置き換えます。
そして
代入式のタイプは、左辺値変換後の左オペランドのタイプです。
~
演算子をc
に適用すると、int
に昇格され、結果もint
になります。
その後
unsigned char
に変換され、次にsigned int
にプロモートされて出力されます。signed int
として出力されます。それはop -5を与えます。なぜうまくいかなかったのですか?
の代わりに:
printf("%d",~c);
使用する:
printf("%d", (unsigned char) ~c);
最初の例と同じ結果が得られます。
~
オペランドは整数の昇格を受け、デフォルトの引数の昇格は可変個関数の引数に適用されます。
標準からの整数昇格:
符号付き整数型のオペランドの型が、符号なし整数型のオペランドの型のすべての値を表すことができる場合、符号なし整数型のオペランドは、符号付き整数型のオペランドの型に変換されます。