Version 4.09
定数を使おう!
「これまで見てきたのは〈変数〉でした。だから……」
void Variable()
{
int i = 0;
TRACE( "%d\n", i ); // 0
i = 100;
TRACE( "%d\n", i ); // 100
}
「と、 i の中身は変えることができます」
『当たり前じゃない』
「でも、場合によっては〈変えたくない〉ってこともない?」
『……年齢が変数なら変えたくないなー』
「そーゆーことじゃなくって」
『んー、たとえば〈自分の電話番号〉とかはそうそう変わんないかな』
「そうそう。あとフラグに使うものも変わらない方がいいかな」
『途中で変わっちゃって永遠にクリアできないとかはヤダなー』
「変数に入れておくと、いつの間にか変えちゃうかもしんない」
『電話番号とかって間違えて教えちゃわないかヒヤヒヤしたりするのよねー。
でも結局は気を付ければいいんじゃないの?』
「看護婦さんは言いました。ちゃんと気を付けました! 点滴のはずだった
んです! って……」
『う”、またそれね……まー確かに〈気を付ける〉のには限界あるよね』
「そこで出てくるのが〈定数〉。これはほいほい変えることができないから
安心」
『変えようとするとどうなるの?』
「ビルドするときにエラーが出るから」
『アプリができないんだ。それなら安心ね』
「さて、まずは〈整数リテラル〉から」
『せーすーりてらる?』
「まぁ〈リテラル〉って〈定数〉って意味だからそのまんまなんだけど、そ
れは置いといて、プログラムのこういうものを整数リテラルって呼びます」
i =
100 // これ!
;
『??』
「つまりプログラム上の数字のことを整数リテラルっていうの」
『あ、なるほど! ってゆーか、なんか変な呼び方して難しくしてない?』
「まー普通使わない言葉だけどね。 MSDN とかには頻繁に出てくるからとり
あえず知っておいて」
『はーい』
「で、いきなりだけど、こういうふうに整数リテラルを直に書くのは御法度
です!」
『ええっ! ってゆーか、しちゃいけないことを教えてたの?』
「いや、絶対にしちゃいけないわけじゃないけどね。こういう小さなテスト
アプリなら問題なし」
『なーんだ』
「でも大きなプログラムだと問題あり。たとえば〈成功のフラグ〉を 1 に
して、それをプログラムに書いちゃったとします」
『書いちゃったとする、と?』
「あとでそのフラグを 2 にしたいときに困っちゃうでしょ」
『そう? 検索して変換すればいいんじゃない?』
「他の用途で 1 って数字使ってたら? そしたら検索して〈それがそのフ
ラグに使うための 1 か〉って確認しなきゃいけないでしょ」
『あ、そういえば』
「だから 1 を FLAG_OK みたいなのに置き換えてプログラムを作れるように
する、っていうのが〈定数〉の基本的な考え方」
『それってどゆこと?』
「 FLAG_OK って名前の変数を作って、そこに 1 を入れれば?」
『あ、なるほど! あとで 2 にしたいときは、 FLAG_OK = 2 みたいにすれ
ば全然問題なし! ってことなんだ』
「そう。で、 FLAG_OK が変数じゃなくて、変えられないようにすればいい
わけ」
『なるほど』
「その方法が実は結構あるから。ひとつずつ見ていくね」
『どれも一長一短あるんだよね』
「そゆこと。まずは #define から」
void Use_define()
{
#define DEF_FLAG_OK 1 // 定数。
int i = DEF_FLAG_OK;
TRACE( "%d\n", i ); // 1
}
『あれ? #define ってどーっかで見たような……』
「ずーっと前に見たね。 #define は1番目のを2番目のに置き換えます」
『ってことは、 DEF_FLAG_OK が 1 に置き換わるんだ。これを 2 にしたい
ときは』
#define FLAG_OK 2
『ってすればいいんだよね』
「そういうこと。これが一番使われてる、定数を実現する方法かな」
『……でもさ、なんか変くない? わざわざタブ打ってないし、 # から始
まってるし、しかもセミコロンで閉じてない!』
「その通り。 #define は〈プリプロセッサ〉ってもののひとつで、ちょっ
と特殊で難しいもの」
『う”、難しいんだ』
「だからちゃんとした説明は今度ってことで、今回は〈これが定数になる〉
ってことだけ憶えておいて」
『ま、置き換わるんだから難しくないよね。あーそうそう、これって定数な
んだから〈値を変えられない〉んだよね』
「……あのさー、 DEF_FLAG_OK = 2 ってして値を変えようとしたら、実際
にどうなる?」
『 1 に置き換わるんだから 1 = 2 、あーこりゃダメだね』
「そゆこと。さて、 #define は実際のところちょっと古い方法。今一般的
なのは const を使う方法かな」
void Use_const()
{
const int FLAG_OK = 1; // 定数。
int i = FLAG_OK;
TRACE( "%d\n", i ); // 1
}
『 const って unsigned とかと同じふーに付いてるね』
「 unsigned int が〈符号なしの int 〉って意味だったのと同じように、
const int は〈変えられない int 〉って意味になります」
『つまり int の形容詞よね。あ、 const が〈変えられない〉ってことは、
こーすれば変数が変えられなくなるんだ!』
「そういうこと。こっちの方が、変数と変わらずに使えるからよく使われて
るから」
『でも変えられないんでしょ? FLAG_CK = 2 とかしたら?』
「訊く前に試してみましょう」
『あ、そうだよね……』
error C2166: 左辺値は const オブジェクトに指定されています。
「〈オブジェクト〉はそのまま〈変数〉って読み替えちゃっていいかな」
『ってことは const だからダメってことなんだ。そのままねー』
「こうやってビルドするときにチェックしてくれるから安心、ってこと」
『……そーいえば、変数って最初に数字入れなくても作れたよね……』
const int FLAG_OK_2;
『ってしたら……あ、またエラーだ』
error C2734: 'FLAG_OK_2' : const として宣言されていますが、
初期化されていません。
『あ、これもちゃんとチェックしてくれるんだ!』
「これも安心な部分だね。さて、 const 整数値も定数としてよく使われて
いるんだけど、最近使われ始めているのが enum 」
『いーなむ?』
「って僕は読んでるけど、実際の発音はちょっと違うかな。これ enumerate
って単語の略だし」
『ふーん』
「ま、それはおいといて使い方」
// enum を使った定数。
enum enum_Flags
{
E_FLAG_OK = 1,
E_FLAG_NO = 0
};
// その使用例。
void Use_enum_Flags()
{
enum_Flags eFlag = E_FLAG_OK;
TRACE( "%d\n", eFlag ); // 1
int i = E_FLAG_OK;
TRACE( "%d\n", i ); // 1
}
『関数の前にあるのが enum っての?』
「そう。 enum enum_Flags ってすると、 enum_Flags って型を作ることが
できます」
『へー、なんかクラスみたい』
「ってほどのものじゃないけどね」
『関数の中でその enum_Flags 型の変数作ってるね。そこに……さっきのの
中の E_FLAG_OK を入れてるね』
「 enum の中で」
E_FLAG_OK = 1
「って感じに書くと、これが」
const int E_FLAG_OK = 1;
「みたいな定数と同じ意味になります」
『ほーなるほど。定数だから、 int 型の変数にも入れられるんだ。……っ
てさ、これって意味なくない?』
「 enum_Flags 型の変数を作れるってとこがミソ」
『この例見ると、整数と同じふうに使えてるよね』
「ところが実は、 enum_Flags 型の変数には E_FLAG_OK と E_FLAG_NO しか
入らないんです」
『へ?』
「つまり」
eFlag = 1;
「はエラーになるってこと」
『ほー、つまり int 型とかとは違うってことね』
「これはビットフラグにすごく便利。フラグに使いたくない値は絶対に入ら
ないからね」
『フラグに使うものだけを enum の中で作っちゃえばいいんだ』
「そういうこと」
『まとめると、定数を使う方法は、 #define に const に enum 、だよね。
使い分けは?』
「 #define は古い方法だから使わない。フラグは enum 、それ以外は const
が一番かな」
『はーい』
/*
Preview Next Story!
*/
『つまりさ、間違えてもエラーが出るっていうのがいいんだよね』
「そういうこと。でも火美ちゃんそーゆーの嫌いそう」
『う”っ、そう?』
「自由度高くないとなんかイヤそうだなーとか」
『うん、だって面倒でしょー、 int でいーじゃん』
「間違えちゃうかもよー、失敗するかもよー」
『というわけで次回』
< Version 4.10 アドレスとポインタ >
「につづく!」
『あ、あたしは間違えないもーん』
「毎日枕元でささやいてあげようか、あっ、しまった、やばー、とか」
『よけー間違えちゃうよぉ』