16進数表記と負数
std::hex
変なことを考えてやたら時間を食ってしまった......
事態はchar型を桁あふれさせたことでした。
char c = 0x89; std::cout << (int)c << '\n' // -119
0x89
は10進数だと137。
char型は最大127までなので、-119が出力されるのはまあよし。
次にこれをstd::hex
で16進表記しようとすると、
char c = 0x89; std::cout << std::hex << (int)c << '\n' // 0xffffff89
んん?
負数表現のためにfがたくさんつくのは良いとして......
「0x89
をchar型に入れてstd::hex
で出力したら0xffffff89
になる」ことにめちゃくちゃ違和感を覚えました。
2の補数で負数を表現しているはずだけど、それだと89が出力されるのがおかしいような......
0x89
は2進数だと0000 0000 0000 0000 0000 0000 1000 1001
。
これの2の補数は1111 1111 1111 1111 1111 1111 0111 0111
で、これが16進数だと0xffffff77
。
「0xffffff89
じゃなくて正しくは0xffffff77
なんじゃないの?」と思ってしまいました。
当然この考察は間違いだったわけです。
そもそもchar型に代入してる時点で0x89
は137ではなく-119として扱われています。
言うまでもなく137と-119は別物。
-119は補数表現的に考えると「119を足して0になる値」なので、
0000 0000 0000 0000 0000 0000 0111 0111
(119)の2の補数1111 1111 1111 1111 1111 1111 1000 1001
(-119)が出力されるものとして正しかったです。
16進数に直すと0xffffff89
ですね。一件落着。
こんなのにやたらと考え込んでしまった...