cv修飾子(cv-qualifier)

C++の修飾子(qualifier)には,const修飾子とvolatile修飾子の2種類がある. この2つをあわせて“cv修飾子”(cv-qualifier)と呼んでいる.

unsignedは修飾子じゃないからね

よくある間違いに,unsignedも修飾子だと思っているケースがあるけど, 正しくはunsignedは“型名の一部”であって修飾子ではない. この違いはtypedefで新しい型名をつくってみると明確になる. たとえば,typedef int int32;として,新しく“int32”という型をつくったとする. constは修飾子なので任意の型を修飾でき, f(const int32 n)のように記述できる(サンプルプログラム1). これに対してunsignedは修飾子ではないので f(unsigned int32 n)と書くとコンパイルエラーになる(サンプルプログラム2).

サンプルプログラム1: OK サンプルプログラム2: NG
typedef int int32;

void f(const int32 n)
{
  printf("%u\n", n);
}
typedef int int32;

void f(unsigned int32 n)
{
  printf("%u\n", n);
}
整数型の型名とその省略形
完全な型名省略形
signed char char
signed short int shortshort int
signed int int
signed long int longlong int
unsigned char
unsigned short int unsigned short
unsigned int unsigned
unsigned long int unsigned long

こういう誤解がおこるのは,unsignedというキーワードが,const修飾子と同じように intなどの型名の前に書かれるという構文上の特徴があるからだと思うのだけど, intが正確にはsigned intだということを思い出せば, signed intunsignedで修飾してunsigned signed intになってはヘンだとわかるだろう. また,変数定義などの際に,単にunsignedとかくとunsigned intの意味に解釈されるのも unsignedが単なる修飾子だとするとヘンな感じだ (これがOKなら単にconstと書いたらconst intの意味になるというルールもあるはずだし).

また,constvolatileが,変更できないとか揮発性であるというような, どんな型にも共通の性質を追加しようとするものであるのに対して unsigned(符号なし)は少なくとも数値を格納する型にしかつけられそうにない点も明確な差がある. [これについては,unsignedは整数型にしかつけられませんという制限のある修飾子なんだと無理やり解釈する手が残ってるけども.] いずれにしても,よく考えてみると書き方は似てるけど違うものっぽいとは思うはず.

constはどちらを修飾?

char* sconst修飾子をつける場合, constが書ける位置は3つある.

表1 constを書く位置とその解釈(サンプルプログラム3
# バリエーション sの変更 *sの変更 解釈
1 f1(const char * s); × const charへのポインタと解釈
2 f2(char const * s); × 同上(const char*と解釈)
3 f3(char * const s); × 変数sが定数(const)と解釈
サンプルプログラム4
0001  typedef char* string;
0002
0003  const string f(const string s) {
0004      *s = 'H';
0005      s += 7;
0006      return s;
0007  }

ここまでは わりと知られている話… 問題は次で,たとえば“typedef char* string;”として新しい型stringをつくっておき, これにconstをつけて,“const string s”とすると “const char * s”と解釈されるのか“char * const s”と解釈されるのか,どっち?という問題. 前者ならサンプルプログラム4の4行目がエラーになり,後者なら5行目がエラーになる.

この問題,単純に “const string s”→“const char * s”なので前者が正解と思ったら大間違い. 実際には後者(char * const s)と解釈されるのが正解. なぜこうなるのかというと…

というのが正解.

実験用サンプルプログラム

サンプルプログラム3 表1 constの位置と解釈
サンプルプログラム4 const string sconst char * schar * const sのどっち?
サンプルプログラム5a/5b const intint constと書いてもよい


はたいたかし
2007-01-13
トップ > 開発ツール > C/C++