C言語 | 構造体の宣言 | 型修飾子 - const
この記事では、変更できない値に使う const 型修飾子と、最適化で省略してはならない値に使う volatile 型修飾子を説明する。
読み取り専用の値
宣言には、記憶域クラス指定子、型指定子、型修飾子、宣言子、初期化子を含められる。
記憶域クラス指定子 型指定子 型修飾子 宣言子 初期化子 ...;
最もよく使われる型修飾子は const である。初期化後に値を変更できないことを表す。
const int ciValue = n;
アプリケーション名やバージョンのように共有する値は、プログラム内でリテラルを繰り返さず、一度だけ宣言するとよい。const は意図しない変更から値を保護する。
コード1
#include <stdio.h>
typedef unsigned char BYTE;
const char APPNAME[] = "Kitty on your lap";
const int VERSION = (15 << 8) | 7;
int main() {
/* APPNAME[1] = 'X'; */ /* error */
/* VERSION = 0; */ /* error */
printf("APPNAME = %s\n" , APPNAME);
printf("VERSION = %d.%d\n" , (BYTE)VERSION , (BYTE)(VERSION >> 8));
return 0;
}
配列を const で修飾すると、すべての要素が読み取り専用になる。
ポインターでは const の位置が重要である。読み取り専用データへのポインターは参照先の値を変更できないが、別のアドレスを指すことはできる。
const char *str = buf1;
/* *str = 'a'; */ /* error */
str = buf2; /* OK */
定数ポインターは別のアドレスを指せないが、参照先の値は変更できる。
char *const str = buf1;
*str = 'a'; /* OK */
/* str = buf2; */ /* error */
コード2
#include <stdio.h>
void Function(const char *str) {
/* str[0] = 'X'; */ /* error */
printf("%s\n" , str);
}
int main() {
Function("Kitty on your lap");
return 0;
}
最適化の抑制
volatile 型修飾子は、ハードウェアや別の権限を持つプロセスなど、現在のプログラム以外から値が変更される可能性をコンパイラーへ伝える。
volatile int viValue = n;
コンパイラーは以前の値がそのまま有効だと仮定せず、必要なときにvolatile値を読み取る。
コード3
#include <stdio.h>
volatile int viVariable = 0xFF;
const volatile char *str = "Kitty on your lap";
int main() {
printf("viVariable = %d\nstr = %s\n" , viVariable , str);
return 0;
}
const と volatile は同時に指定できる。この場合、現在のプログラムは値を変更できないが、外部から変更される可能性はある。