nislandのブログ

いろんなジャンルについて書くつもりです

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ですね。一件落着。
こんなのにやたらと考え込んでしまった...