第7回 修飾子と記憶クラス指定子

C言語にもC++と同じ修飾子(const および volatile)や記憶クラス指定子(extern, static, auto, register, および typedef)が備わっています。ただし、mutable 記憶クラス指定子はありません。また、微妙に仕様が異なるものがあるため、ここではそれらについて解説します。

const 修飾子

const 修飾子の振る舞いは、C++とC言語ではかなり異なるので注意が必要です。

非局所オブジェクトはデフォルトで外部結合

第2回でも触れましたが、const 修飾子の有無にかかわらず、関数の外で宣言した非局所オブジェクトは、明示的に static 記憶クラス指定子を付けないかぎり外部結合になります。

汎整数定数式にはならない

C++では、const 修飾子付きの汎整数型オブジェクトは、列挙定数などと同じように汎整数定数式として扱うことができました。しかし、C言語ではそのような例外的な仕様はなく、あくまでも普通のオブジェクトとして振る舞います。したがって、const 修飾子付きの汎整数型オブジェクトを、列挙定数の値や配列の要素、case ラベルの値などに使うことはできません。

const int N = 10;
int array[N];  /* エラー */
enum { foo = N };  /* エラー */
etc.

mutable 記憶クラス指定子

C言語には mutable 記憶クラス指定子はありません。したがって、const 修飾子付きで宣言された構造体型のオブジェクトのすべてのメンバは更新することができません。

register 記憶クラス指定子

register 記憶クラス指定子がヒント情報に過ぎないことは、C言語でも同じです。しかし、あくまでもレジスタに割り付けることを前提としていますので、register 記憶クラス指定子を付けて宣言したオブジェクトは、& 演算子を使ってアドレスを取得することができません。

int main(void)
{
  register int a = 0;
  int *p = &a;  /* エラー */
}

typedef 記憶クラス指定子

C++では、同じ内容であれば、同一の翻訳単位に typedef を使った複数の型定義を記述してもエラーになりませんでした。しかし、C言語ではそうした記述はエラーになります。

typedef int a;
typedef int a;  /* エラー */
 
int main(void)
{
  return 0;
}

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/569
このエントリーを含むはてなブックマーク