[C99] 第7回 修飾子と記憶クラス指定子
C99にもC++と同じ修飾子(const および volatile)や記憶クラス指定子(extern, static, auto, register, および typedef)が備わっています。ただし、mutable 記憶クラス指定子はありません。逆に、C++にはない restrict 修飾子があります。また、微妙に仕様が異なるものがあるため、ここではそれらについて解説します。
const 修飾子
const 修飾子の振る舞いは、C++とC99ではかなり異なるので注意が必要です。
非局所オブジェクトはデフォルトで外部結合
第2回でも触れましたが、const 修飾子の有無にかかわらず、関数の外で宣言した非局所オブジェクトは、明示的に static 記憶クラス指定子を付けないかぎり外部結合になります。
汎整数定数式にはならない
C++では、const 修飾子付きの汎整数型オブジェクトは、列挙定数などと同じように汎整数定数式として扱うことができました。しかし、C99ではそのような例外的な仕様はなく、あくまでも普通のオブジェクトとして振る舞います。したがって、const 修飾子付きの汎整数型オブジェクトを、列挙定数の値や、静的な配列の要素、case ラベルの値などに使うことはできません。
static int array[N]; /* エラー */
enum { foo = N }; /* エラー */
etc.
restrict 修飾子*1
C99には、C++にはない restrict 修飾子というものがあります。restrict 修飾子はポインタしか修飾することができません。restrict で修飾された複数のポインタは、それぞれが同じオブジェクトを指していないこと意味します。つまり、restrict 修飾子は、register 記憶クラス指定子や inline 関数指定子のように、コンパイラに対するヒント情報ということになります。
ところで、C++では、const 修飾子と volatile 修飾子をあわせて「cv修飾子」と呼んでいますが、C99では restrict 修飾子を含めて3種類あるため「型修飾子」と呼びます。
mutable 記憶クラス指定子
C99には mutable 記憶クラス指定子はありません。したがって、const 修飾子付きで宣言された構造体型のオブジェクトのすべてのメンバは更新することができません。
register 記憶クラス指定子
register 記憶クラス指定子がヒント情報に過ぎないことは、C99でも同じです。しかし、あくまでもレジスタに割り付けることを前提としていますので、register 記憶クラス指定子を付けて宣言したオブジェクトは、& 演算子を使ってアドレスを取得することができません。
{
register int a = 0;
int *p = &a; /* エラー */
}
typedef 記憶クラス指定子
C++では、同じ内容であれば、同一の翻訳単位に typedef を使った複数の型定義を記述してもエラーになりませんでした。しかし、C99ではそうした記述はエラーになります。
typedef int a; /* エラー */
int main(void)
{
return 0;
}
この記事のトラックバックURL:
ブックナビゲーション
- 技術情報
- Boost C++ Libraries メモ
- C++と組込み環境
- C++サンプル集
- C++テンプレート集
- C++プログラマのためのC言語入門
- C/C++迷信集
- C99関数・マクロ・前処理スクリプト集
- C言語再入門
- C言語徹底入門
- Drupal メモ
- TOPPERS 情報
- ベターCとしてのC++
- マイコン メモ
- ライブラリ開発入門
- 分割コンパイルをきわめる
- 擬似プロセッサを作る
- 象の卵を探して...
- 車輪の再発明
- 過去の情報


constの「汎整数定数式にはならない」にある int
constの「汎整数定数式にはならない」にある
int array[N]; /* エラー */
ですが、これは可変長配列になるのでエラーではないはずです。
コメントありがとうございます。
ご指摘通りです。元データをC99用に直す際にチェック漏れがありました。修正しておきます。