定数と型
データを直接コードに書く
プログラムの中に直接書かれた値は、何度プログラムを実行しても変化することはありません。このような固定値のことを定数(constant)と呼びます。標準 C++ など別の文書ではリテラル(literal)と呼ぶこともありますが、基本的な意味は同じです。
これまでのプログラムで表示してきた、二重引用符で括った文字列は、文字列定数と呼ばれる定数の一種です。この他にも 10 や 3.14 などの数値など、定数は扱うデータに応じて次のいずれかに分類できます。
- 整数定数
- 浮動小数点定数
- 文字定数
- 列挙定数
このように定数が分類されているのは、データの種類によって表現方法や操作方法が異なるためです。例えば、文字列と数値は互いに計算できないということは容易に想像できると思います。これらの定数は、互いにデータとしての表現方法が大きく異なっています。このような、データの表現方法や操作方法の違いに応じて扱いを区別するために型 (Type)という概念が用いられます。文字列と数値は型が異なるのです。
上記の定数の種類は、定数が表現するデータ型ごとに分類されています。整数定数は整数型のデータを記述するための記法であり、文字列定数は文字列型のデータを記述するための記法です。
以下では、最も基本である整数、浮動小数点数、文字の 3 種類の定数の書き方を紹介します。最後の列挙定数(enumeration-constant)に関しては後述します。
整数定数
整数定数(integer-constant)は、小数点以下を含まない整数をコード内で表します。これは、私たちが普段日常で使っている数と同じだと思ってかまいません。つまり、コード内に書かれている 10 や 1234 といった値は整数定数であると解釈できます。
このとき、数字を二重引用符 " で囲まないでください。二重引用符に囲まれている部分は文字列定数として解釈されます。整数定数は数値として扱われ、文字列定数は文字の並びとして扱われます。定数として表記された 1234 は整数定数、"1234" は文字列定数として処理されるのです。数値と文字列は型が異なるため、保存方法や値の操作方法も、それぞれ異なります。
これまで二重引用符で囲った文字列を出力してきたように、他の定数も同じ方法で printf() 関数で出力できます。文字列以外の値を printf() 関数で出力するには書式指定と呼ばれる、値の表示方法を指定する特殊な記号を文字列内に挿入します。書式指定は高度な表現力がありますが、詳細まで解説すると複雑になります。この場では、書式指定は % 記号で始まり、表示したい値の型を指定する文字が続くと考えてください。
書式指定文字 | 引数型 | 変換結果 |
---|---|---|
%d 又は %i | int | 10進整数 |
%x | int | 符号なし16進数。9 以降は"abcdef"を使用 |
%X | int | 符号なし16進数。9 以降は"ABCDEF"を使用 |
%c | int | 文字 |
%s | char * | 文字列 |
%f | double | 浮動小数 [-]dddd.dddd 形式 |
%e | double | 浮動小数 [-]d.dddd e[+/-]ddd 形式 |
%E | double | 指数の前に付くのが e ではなく E である点を除いて、%e の書式と同じ |
%g | double | %f 又は %e のうち、指定値及び精度で表現可能な短い方の書式 |
%G | double | 指数の前にあるのが e ではなく E である点を除いて、%g の書式と同じ |
%% | -- | 変換せずに % を表示する |
printf() 関数は第 2 引数以降、任意の数だけ引数を指定することができ、最初の第 1 引数には書式制御文字列を指定します。書式制御文字列には % 記号を用いた書式指定を用いることができ、printf() 関数は最初の書式指定を見つけると、第 2 引数の変数を指定した形で出力し、2 番目の書式指定を見つければ、第 3 引数の変数を指定した形で出力するというような仕組みになっています。そのため、書式制御文字列に存在する書式指定の数だけ、第 2 引数以降に変数を指定します。書式指定より引数の数が多いと、余分な引数は無視されますが、書式指定より引数の数が少ない場合、動作は保証されません。
printf() 関数で文字列内に整数を組み込むには %d 書式指定文字を使います。
#include <stdio.h> int main(void) { printf("%d\n", 10); printf("%d\n", 2525); return 0; }
コード1は整数定数を出力した例です。コード上に書かれている整数値が、そのまま結果として表示されています。
0 以外の数字で始まる整数定数は 10 進数と解釈されますが、それ以外に 8 進数と 16 進数で整数を表すこともできます。コンピュータの内部では、あらゆるデータが 2 進数で保存されているため、プログラムが扱うデータによっては 8 進数や 16 進数で記述した方が便利になることがあります。
8 進数の整数定数は 0 から始まり 0 ~ 7 までの数字の組み合わせで表します。8 進数定数で使える数字は 0 ~ 7 の範囲だけなので 07 の次は桁を増やして 010 (10進数における 8)になります。
16 進数の整数定数は 0x から始まり 0 ~ 9 までの数字と A ~ F までのアルファベット、または a ~ f までのアルファベットで表せます。16 進数では 9 以降の値を A ~ F までのアルファベットで表すことができるため 0xF (10 進数における 15)の次で桁が増えて 0x10 となります。アルファベットの大文字と小文字の組み合わせは自由ですが、通常はどちらか一方に統一します。
2進数 | 8進数 | 10進数 | 16進数 |
---|---|---|---|
0000 0001 | 01 | 1 | 0x1 |
0000 0010 | 02 | 2 | 0x2 |
0000 0011 | 03 | 3 | 0x3 |
0000 0100 | 04 | 4 | 0x4 |
0000 0101 | 05 | 5 | 0x5 |
0000 0110 | 06 | 6 | 0x6 |
0000 0111 | 07 | 7 | 0x7 |
0000 1000 | 010 | 8 | 0x8 |
0000 1001 | 011 | 9 | 0x9 |
0000 1010 | 012 | 10 | 0xA |
0000 1011 | 013 | 11 | 0xB |
0000 1100 | 014 | 12 | 0xC |
0000 1101 | 015 | 13 | 0xD |
0000 1110 | 016 | 14 | 0xE |
0000 1111 | 017 | 15 | 0xF |
0001 0000 | 020 | 16 | 0x10 |
8 進数の 1 桁は 2 進数の 3 桁に対応し、16 進数の 1 桁は 2 進数の 4 桁 に対応していることが表2から確認できます。多くの場合、コンピュータの内部で管理されている 2 進数のデータは 4 桁または 8 桁単位で操作することになるため、特に 16 進数による表記は重要です。
#include <stdio.h> int main(void) { printf("10=%d\n", 10); printf("010=%d\n", 010); printf("0x10=%d\n", 0x10); return 0; }
コード2は 10 進数で表記された整数定数 10 と、8 進数で表記された整数定数 010、16 進数で表記された 0x10 を出力しています。結果はすべて 10 進数で表示されます。10 は見たまま 10 と出力されますが、8 進数 010 は 8、16 進数 0x10 は 16 と表示されています。
定数で表現できる最大範囲は C 言語の仕様では定められていないため処理系に依存します。
浮動小数点定数
整数部と少数部から構成される実数は浮動小数点定数(floating-constant)として表記できます。浮動小数点定数の記法は、一般的な実数の書き方と同じで、数字列からなる整数部と小数部をピリオド . で区切ります。浮動小数点定数には、整数定数で使われていた 8 進数 16 進数はつかえません。
3.141592
上記は整数部が 3、小数部が 141592 からなる浮動小数点定数です。上記のような整数部と小数部で構成されたピリオドで区切られた数字列の組み合わせを小数点定数(fractional constant)とも呼びます。整数部または小数部のいずれかを省略することができ、省略された場合は 0 と解釈されます。
.123 //0.123 123. //123.0
よって 0.123 と .123 は同じ値です。
printf() 関数で文字列内に浮動小数点数を組み込む書式指定文字は表記法に応じて 3 種類が用意されています。1 つは固定桁数で整数部と小数部をそのまま表示する %f 書式指定文字、さらに指数部を加えて表示する %e 及び %E 書式指定文字、そして、そのどちらかの記法のうち、より短い最適な表現で表示する %g 書式指定文字です。多くの場合は %g を使うことになるでしょう。
#include <stdio.h> int main(void) { printf("%g\n", 3.1415); printf("%g\n", .1415); printf("%g\n", 3.); return 0; }
浮動小数点定数は指数部(exponent part)を持つことができます。指数部は小数点定数または数字列の後にアルファベットの e または E に続けて指数を記述します。指数部を持つ定数を記述することで、基数 10 の累乗の値を表現できます。
1.234e2 //123.4 123e3 //123000 .01234e4 //123.4
指数部には + または - 記号を数字列の前に置いて符号を指定できます。符号を書かなかった場合は正の数と解釈されるため、正数を表す + 記号を記述した場合と同義です。一方、指数部が負数であることを表すには - 記号による符号を明記しなければなりません。
12.34e+1 //123.4 12.34e-1 //1.234
これらの指数表記を用いることで、大きな値や小さな値を少ない桁で表すことができます。
#include <stdio.h> int main(void) { printf("1.234e2=%g\n", 1.234e2); printf("123e2=%g\n", 123e2); printf(".01234e4=%g\n", .01234e4); printf("12.34e+1=%g\n", 12.34e+1); printf("12.34e-1=%g\n", 12.34e-1); return 0; }
コード4は指数部を持つ浮動小数点定数を出力しています。例えば、指数表記を用いた浮動小数点定数 1.234e2 の出力結果から、これは 1.234 × 102 に等しいことが確認できます。
文字定数
文字定数(character-constant)は、アルファベットや記号などの任意の 1 文字を表します。複数の文字の並びで構成される文字列と混同しないように注意してください。詳細は後述しますが、文字列は上記のような文字データが列になって並んでいる状態です。文字定数は引用符 ' で文字を囲みます。
'A'
当然、文字定数を表す引用符 ' 内に複数の文字を記入することはできません。例えば 'ABC' というような文字定数はエラーになります。二重引用符 " で括った文字列とは区別されるので注意してください。また、文字定数の途中で改行はできません。
ただし、エスケープシーケンス(escape sequence)と呼ばれる特殊な文字は複数の記号と文字の組み合わせで 1 文字と解釈されます。例えば、表示できないタブ文字や改行をエスケープシーケンスで表すことができます。エスケープシーケンスは円記号 \ から始まり、続く文字や記号で 1 文字を表現します。
エスケープ文字 | 意味 |
\a | ベル文字(アラート) |
\b | 1文字分戻る |
\f | ページ送り(クリア) |
\n | 改行 |
\r | 同じ行の先頭に戻る |
\t | 水平タブ |
\v | 垂直タブ |
\' | 引用符 |
\" | 二重引用符 |
\? | はてな ? |
\\ | 円記号(バックスラッシュ) |
\ooo | 8進定数(o は8進数の値) |
\xhhh | 16進定数(h は16進数の値) |
文字列内で二重引用符を用いたい場合や、文字定数で引用符を表現する場合、または \ 記号やタブ文字などを表現したい場合に表3のエスケープ文字を使います。ただし、垂直タブなど一部の文字は特定のデバイスでしか意味を成さない場合もあります。なお、システムやフォント、言語環境によって円記号ではなくバックスラッシュで表示されることがありますが同じです。
printf() 関数で 1 文字を表示するには %c 書式指定文字を使います。
#include <stdio.h> int main(void) { printf("A=%c\n", 'A'); printf("ベル文字=%c\n", '\a'); printf("円記号=%c\n", '\\'); printf("16進数 x61=%c\n", '\x61'); return 0; }
コード5は複数の文字定数を出力しています。文字定数は 1 文字を表すデータなので、通常の文字は引用符内に 1 文字(記号)しか指定できません。ただし、エスケープ文字は \ 記号と他の文字で 1 文字と解釈されます。