コードを確認するとき、次のルールを適用します。
const
関数が指すデータを変更(または解放)しない場合、参照によって渡される関数パラメーターに常に使用します。
int find(const int *data, size_t size, int value);
const
それ以外の場合は#defineまたは列挙を使用して定義される定数に常に使用します。コンパイラーは、結果として読み取り専用メモリー(ROM)内のデータを見つけることができます(ただし、組み込みシステムでは、この目的にはリンカーがより良いツールであることがよくあります)。
const double PI = 3.14;
valueによって渡されるパラメーターの関数プロトタイプで
constを使用しないでください。それは意味を持たないため、単なる「ノイズ」です。
// don't add const to 'value' or 'size'
int find(const int *data, size_t size, const int value);
必要に応じて、const volatile
プログラムでは変更できないが、変更される可能性がある場所で使用します。ハードウェアレジスタは、ここでの典型的な使用例です。たとえば、デバイスの状態を反映するステータスレジスタです。
const volatile int32_t *DEVICE_STATUS = (int32_t*) 0x100;
他の用途はオプションです。たとえば、関数実装内の関数へのパラメーターはconstとしてマークできます。
// 'value' and 'size can be marked as const here
int find(const int *data, const size_t size, const int value)
{
... etc
または取得され、その後変更されない値または計算を返す関数:
char *repeat_str(const char *str, size_t n)
{
const size_t len = strlen(str);
const size_t buf_size = 1 + (len * n);
char *buf = malloc(buf_size);
...
これらの使用はconst
、変数を変更しないことを示しています。変数の保存方法や場所は変更されません。もちろん、コンパイラーは変数が変更されていないことconst
を確認できますが、追加することでそれを強制できます。これは読者を助け、ある程度の安全性を追加することができます(ただし、関数が大きくて複雑で、これが大きな違いを生む場合は、おそらく他の問題があります)。編集-例 ネストされたループと多くの長いまたは同様の変数名を持つ200行の密にコード化された関数で、特定の変数が決して変わらないことを知っていると、わかりやすくなります。このような機能は、設計が不十分であるか、メンテナンスされています。
の問題const
。おそらく「中毒」という言葉を聞くでしょう。これはconst
、関数パラメーターに追加すると「安定性」が伝播する場合に発生します。
編集-constポイズニング:たとえば関数内:
int function_a(char * str, int n)
{
...
function_b(str);
...
}
に変更str
する場合はconst
、それfuction_b
もconst
。そして、そうであればfunction_b
合格str
とにfunction_c
あなたはそれが多くの別々のファイル/モジュールに伝播する場合、これは痛みを伴う可能性が想像できるようになど、。変更できない関数(システムライブラリなど)に伝播する場合、キャストが必要になります。その
const
ため、既存のコードを振り回すことは、おそらく問題を求めています。ただし、新しいコードではconst
、必要に応じて一貫して修飾することをお勧めします。
よりconst
in な問題は、元の言語ではなかったことです。アドオンとしては完全に適合しません。開始には、2つの意味があります(上記のルールのように、「これを変更しません」と「これは変更できません」を意味します)。しかし、それ以上に危険な場合があります。たとえば、このコードをコンパイルして実行すると、(コンパイラ/オプションに応じて)実行するとクラッシュする可能性があります。
const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '\0';
strchr
char*
not aを返しますconst char*
。呼び出しパラメーターである
const
ため、呼び出しパラメーターをにキャストする必要がありますchar*
。そして、この場合、実際の読み取り専用ストレージプロパティを捨てます。編集:-これは一般的に読み取り専用メモリ内の変数に適用されます。「ROM」とは、物理的なROMだけでなく、一般的なOSで実行されるプログラムのコードセクションで発生する書き込み保護されたメモリを意味します。
多くの標準ライブラリ関数は同じように動作するため、注意してください。実際の定数(つまり、ROMに格納されている)がある場合、その定数を失わないように注意する必要があります。
Specific issues with software development
。私は非常に具体的です。