LoginSignup
9
6

More than 3 years have passed since last update.

char を数字として出力したい!

Last updated at Posted at 2016-03-17

charといえば、もっぱら文字を表すのに使われる型で、std::coutはそれを前提とした動作をする。

具体的には…

char c = 65 // 文字コードがASCIIなら'A'と同じ
std::cout << c << std::endl

出力
A

流れに逆らう

では、もしcを文字ではなく数字として出力したい場合はどうするか。

ググってみるとStack Overflowにこんなのが。
http://stackoverflow.com/questions/14644716/how-to-output-a-character-as-an-integer-through-cout

投票数の多い回答を見ると、単項演算子+cに付けるだけでよいという。

つまり、

char c = 65 // 文字コードがASCIIなら'A'と同じ
std::cout << +c << std::endl

出力
65

仕組みはよくわからないが、元のページによれば「数字として表示される型に昇格される」らしい。
つまりはintとかにキャストするのと同じなのだろうか。

動機

自分はcharそのものに興味はないのだが、int8_tuint8_tは処理系によってはsigned charunsigned charをtypedefすることで実装されている。
typedefされた型はテンプレート特殊化では元の型と同じ扱いなので、単なる数値型としてint8_tを使ってもchar向けの特殊化の影響を受けてしまう。
これを回避する方策を探していたのだった。

(噂に聞く「強いtypedef」とかいうのがあればこういう問題もなくなるのだろうか…)

(2021/2/8追記)原理

約5年経ち「C++完全に理解した」ので原理について調べてみる。
C++ドラフトの[expr.unary.op]の単項+演算子の項には以下のような記載がある。

Integral promotion is performed on integral [...] operands.
The type of the result is the type of the promoted operand.

つまり、単項+演算子のオペランドには"integral promotion"なるものが働き、戻り値はその結果の型になるらしい。

"integral promotion"については[conv.prom]に以下のような記載がある。

A prvalue of an integer type [...] can be converted to a prvalue of type int

略した部分を含めて大雑把に言えば「intよりも小さい数値型のprvalueはint型のprvalueに変換できる」ということだ。

だが一点問題がある。変数は確かlvalueとかそのへんのやつで、少なくともprvalueではないはずだ。
これに関しては"lvalue-to-rvalue conversion"というのがあるらしい。([conv.lval])

A glvalue [...] can be converted to a prvalue.

この記事によると、glvalueはlvalueとその他の概念の総称らしいので、変数には適用できそうだ。

この2つの変換が合わさって、表題のような効果が得られるのだろう。

参考: https://en.cppreference.com/w/c/language/conversion

9
6
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6