本当に不変?C言語のconst型修飾子
#include <stdio.h> int main( void ) { const int value = 10; value = 10; //コンパイルエラーが出る return 0; }
こうすると、「 error C2166: 左辺値は const オブジェクトに指定されています。」の様に、コンパイルエラーが出て、変数を変更することを防げます。この例をみると、const型修飾子は簡単なものだと感じるでしょう。
しかし、const型修飾子はポインタが絡むと複雑になります。const型修飾子付きポインタ変数を使ったサンプルを見て下さい。
#include <stdio.h> int main( void ) { int value = 10; int value1 = 20; const int* ptr = &value; printf( "初期値%d\n", *ptr ); //*ptr = 20; //コメントを外すとエラーが発生 ptr = &value1; //変更してもエラーが出ない printf( "現在の値%d\n", *ptr ); return 0; }
期待通り*ptr = 20;の様なコードで変数を直接変更する事は出来ません。しかし、ポインタの値を変更する事により値を変更できます。ポインタの値を変更する事を防ぐには、const型修飾子を使って、変数を定数ポインタとして宣言します。
#include <stdio.h> int main( void ) { int value = 10; int value1 = 20; int * const ptr = &value; printf( "初期値%d\n", *ptr ); *ptr = 20; //今度は直接値を変更出来てしまう //ptr = &value1; //コメントを外すとエラーが発生 printf( "現在の値%d\n", *ptr ); return 0; }
今度は逆に、ポインタの値は変更できないものの、変数の値は直接変更出来てしまいます。ポインタおよび変数の値の両方を不変にしたければ、const型修飾子を2回指定します。
#include <stdio.h> int main( void ) { int value = 10; int value1 = 20; const int * const ptr = &value; printf( "初期値%d\n", *ptr ); //*ptr = 20; //コメントを外すとエラーが発生 //ptr = &value1; //コメントを外すとエラーが発生 printf( "現在の値%d\n", *ptr ); return 0; }
こうすれば変数を不変にできると、考える人もいるでしょう。しかし、これでもまだ値を変更する方法が存在します。
#include <stdio.h> int main( void ) { int value = 10; int * const x = &value; const int * const ptr = &value; printf( "初期値%d\n", *ptr ); //他の変数を使用して値を変更 *x = 20; printf( "現在の値%d\n", *ptr ); //直接値を変更 value = 100; printf( "現在の値%d\n", *ptr ); return 0; }
このサンプルが示すように、const型修飾子は間接的に値を変更する事を防げません。また、参照元の変数を直接変更できる事も忘れてはなりません。
const型修飾子は定数を指定したい時に使用されますが、実際は定数ではありません。constを指定した変数は代入出来ない事を意味しているだけなのです。const型修飾子を指定しても変数は変更される恐れがあります。従って、チーム開発でプログラミングをする場合、コーディングルールが重要だと言えます。
const型修飾子を使用する際には、十分に注意しましょう。