マジックナンバー (プログラム)
プログラムにおけるマジックナンバー(英: magic number、魔法の数字)とは、何らかの識別子もしくは定数として用いられる、プログラムのソースコード中に書かれた具体的な数値である。そのプログラムを書いた時点では製作者は数値の意図を把握しているが、他のプログラマーまたは製作者本人がマジックナンバーの意図を忘れたときに閲覧すると「この数字の意味はわからないが、とにかくプログラムは正しく動く。まるで魔法の数字だ」という皮肉を含む。
概要
[編集]次のような理由で、マジックナンバーはプログラム中に含まれないことが好ましいとされる。
- その数値の持つ意味がわかりづらい。
- 数値を変更する場合に、複数の箇所を変更しなければならない可能性がある。
- 例1
たとえば、消費税が8%の時に、税込価格 (tax-included price) を求める以下のようなソースコードをC言語で書いたとする。
double calculateTaxIncludedPrice(double price) {
return 1.08 * price;
}
これは、price
に商品の本体価格を入力することで消費税込みの価格が得られる、という計算式を実装する関数である。しかし消費税の税率 (tax rate) は変化し得るため、税率が8%以外に変更されたとき修正が必要となる。このとき「1.08」はマジックナンバーであり「なぜ1.08なのか」という意図が不明瞭である。
ここで、マジックナンバーを取り除くため、名前付きの定数シンボルTaxRate
を導入する。
double calculateTaxIncludedPrice(double price) {
const double TaxRate = 0.08;
return (1.0 + TaxRate) * price;
}
定数シンボルの導入により、式に意図が反映されるため修正が容易になる。
- 例2
printColorText()
関数は第1引数の文字列を、第2引数でRGBのフルカラー値として指定した色で印字する関数であるとする。
extern void printColorText(const char* text, uint32_t colorValue);
printColorText("color text", 0x9acd32);
この場合、"color text"という文字列が「黄緑色」で表示される。ただし0x9acd32は直感的に「黄緑色」と伝えることは困難なマジックナンバーである。
マジックナンバーを取り除く手法の一つとして、以下のような書き方がある。
const uint32_t YellowGreen = 0x9acd32;
printColorText("color text", YellowGreen);
これらマジックナンバーを避けるため、マジックナンバーが書いてある箇所を定数や列挙型に置き換えるといった処置がとられる。定数は意味のわかりやすいような名前を付けることができるため、一読して数値の意味を理解できるからである。ここで、定数の初期化の際に右辺値に書かれる数値までマジックナンバーやハードコーディングとは呼ばない。
また、1や0はそれ自体が「真」・「偽」などの意味(真理値)を示しうる数値であり、使われる文脈によってはマジックナンバーとは呼ばないこともある。古いC言語では、意味を明確にするため、1/0の数値を直接用いるのではなく、TRUE
やFALSE
といったシンボルを明示的に定義して利用することがあった。
#define TRUE 1
#define FALSE 0
現在のC言語規格案では、
_Bool Definitions For true and false.
を採用している[1]。
フォーマット識別子
[編集]マジックナンバーは、データ構造体の中にある本質的な意味を持たない数値を指すことがある。これはデータ構造体を識別し、間違った型として扱われる事を防ぐために使われる。これについてはフォーマット識別子としてのマジックナンバーを参照。
関連用語
[編集]プログラムに直接書き込んでしまう具体的な値は数値に限らない。特定のファイルのフルパスを表す文字列を埋め込むこともままある。
このようにマジックナンバーを含めてプログラムに決め打ちの値を埋め込むことを、ハードコーディングと言う。
出典
[編集]- ^ ISO IEC 9899 Programming language C WDN2731 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2731.pdf