📦 変数・型・演算子
🎯 constとconstexpr(C23)を使い分け、変わらない値を宣言時に固定できる
プログラムには「絶対に変わってほしくない値」があります。消費税率、円周率、1週間の日数。これを普通の変数にしておくと、どこかで書き換わっても気づけません。値に鍵をかけるのがconstです。
const——書き換え禁止の箱
#include <stdio.h>
int main(void) {
const double ZEIRITSU = 1.10;
int honntai = 1200;
printf("税込 %.0f 円\n", honntai * ZEIRITSU);
// ZEIRITSU = 1.08; // ここを有効にするとコンパイルエラー
return 0;
}const を付けた変数は、初期化のときにだけ値を持てます。あとから代入しようとすると、コンパイルの時点でエラーになって止まります。実行してから気づくはずだったバグが、書いた時点で防げるわけです。
定数名は大文字で書く習慣があります。読む人に「これは変わらない」と一目で伝わります。
constexpr——C23の「コンパイル時に決まる定数」
#include <stdio.h>
int main(void) {
constexpr int TSUKI = 12;
constexpr int NENKAN = 365;
constexpr int HEIKIN = NENKAN / TSUKI;
printf("1か月あたり約 %d 日\n", HEIKIN);
return 0;
}constexprはC23で入った書き方で、「この値はコンパイルの時点で確定している」という宣言です。const との違いは、コンパイラが値そのものを知っていること。そのおかげで、配列の要素数(トラック8)のような「コンパイル時に決まっていなければならない場所」でも使えます。
#define との違い
#include <stdio.h>
#define ZEI_A 1.10 // 単なる文字の置き換え。型が無い
int main(void) {
const double ZEI_B = 1.10; // 型のある定数
constexpr double ZEI_C = 1.10; // 型があり、コンパイル時に確定
printf("%.2f %.2f %.2f\n", ZEI_A, ZEI_B, ZEI_C);
return 0;
}#define はコンパイル前に文字を機械的に置き換えるだけの指示です(トラック16で詳しくやります)。型のチェックが効かず、エラーメッセージも読みにくくなります。C23ではまず constexpr、次に const、#define は最後の手段と考えておけば十分です。
罠・注意
const は宣言と同時に初期化する。 const int N; N = 5; はエラーです。鍵をかけてから中身を入れることはできません。
constexpr の右辺は定数式だけ。 scanf で読んだ値のように、実行時にしか決まらないものは入れられません。
古い環境では constexpr が通らない。 C23対応のコンパイラが必要です(gcc 13以降など)。通らない環境では const で代用します。
まとめ
const は書き換え禁止の変数、constexpr(C23)はコンパイル時に値が確定する定数です。どちらも「変わらないもの」を宣言時に明示して、事故を書いた時点で止めるための道具。型のない #define より、型のある定数を優先します。
一度値を入れたら変更できないようにする修飾子のこと。うっかり書き換えてしまうミスをコンパイラの側で防いでくれる働きを持つ。定数として扱いたい値には積極的に付けておくと安全性が高まる。
コンパイル時に値が確定する定数を宣言するC23のキーワードのこと。従来のマクロ定数より型安全で、デバッグ情報も残るという利点がある。#defineによるマクロ定数の、より安全な後継として位置づけられている。
変数に入れられる値の種類と、確保するメモリの大きさを決める分類のこと。箱の形や大きさを決めるルールのようなものだと考えるとよい。int・double・charなど、C言語にはあらかじめ複数の型が用意されている。
ソースコードをコンピュータが直接実行できる機械語に変換する作業。翻訳者が人間の言葉を機械の言葉に訳してくれる工程だとイメージすると分かりやすい。この工程を経なければ、書いたコードはコンピュータの上でまったく動かせない。
もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。