JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
Oracle Solaris Studio 12.2: C ユーザーガイド
search filter icon
search icon

ドキュメントの情報

はじめに

1.  C コンパイラの紹介

2.  C コンパイラ実装に固有の情報

3.  C コードの並列化

4.  lint ソースコード検査プログラム

5.  型に基づく別名解析

6.  ISO C への移行

6.1 基本モード

6.1.1 -Xc

6.1.2 -Xa

6.1.3 -Xt

6.1.4 -Xs

6.2 古い形式の関数と新しい形式の関数の併用

6.2.1 新しいコードを書く

6.2.2 既存のコードを更新する

6.2.3 併用に関する考慮点

6.3 可変引数を持つ関数

6.4 拡張: 符号なし保存と値の保持

6.4.1 背景

6.4.2 コンパイルの動作

6.4.3 例 1 : キャストの使用

6.4.4 ビットフィールド

6.4.5 例 2 : 同じ結果

6.4.6 整数定数

6.4.7 例 3 : 整数定数

6.5 トークン化と前処理

6.5.1 ISO C の翻訳段階

6.5.2 古い C の翻訳段階

6.5.3 論理的なソース行

6.5.4 マクロ置換

6.5.5 文字列の使用

6.5.6 トークンの連結

6.6 const と volatile

6.6.1 右辺値 (lvalue) 専用の型

6.6.2 派生型の型修飾子

6.6.3 const は readonly を意味する

6.6.4 const の使用例

6.6.5 volatile は文字どおりの解釈を意味する

6.6.6 volatile の使用例

6.7 複数バイト文字とワイド文字

6.7.1 アジア言語は複数バイト文字を必要とする

6.7.2 符号化の種類

6.7.3 ワイド文字

6.7.4 変換関数

6.7.5 C 言語の機能

6.8 標準ヘッダーと予約名

6.8.1 標準ヘッダー

6.8.2 実装で使用される予約名

6.8.3 拡張用の予約名

6.8.4 安全に使用できる名前

6.9 国際化

6.9.1 ロケール

6.9.2 setlocale() 関数

6.9.3 変更された関数

6.9.4 新しい関数

6.10 式のグループ化と評価

6.10.1 定義

6.10.2 K&R C の再配置の権利

6.10.3 ISO C の規則

6.10.4 括弧

6.10.5 as if 規則

6.11 不完全な型

6.11.1 型

6.11.2 不完全な型を完全にする

6.11.3 宣言

6.11.4 式

6.11.5 正当性

6.11.6 例

6.12 互換型と複合型

6.12.1 複数の宣言

6.12.2 分割コンパイル間の互換性

6.12.3 単一のコンパイルでの互換性

6.12.4 互換ポインタ型

6.12.5 互換配列型

6.12.6 互換関数型

6.12.7 特別な場合

6.12.8 複合型

7.  64 ビット環境に対応するアプリケーションへの変換

8.  cscope: 対話的な C プログラムの検査

A.  機能別コンパイラオプション

B.  C コンパイラオプションリファレンス

C.  ISO/IEC C 99 の処理系定義の動作

D.  C99 でサポートされている機能

E.  ISO/IEC C90 の処理系定義の動作

F.  ISO C データ表現

G.  パフォーマンスチューニング

H.  K&R Solaris Studio C と Solaris Studio ISO C の違い

索引

6.6 const と volatile

キーワード const は、ISO C に組み込まれた C++ 機能の 1 つでした。アナログキーワード volatile が ISO C 委員会により考案されたとき、「型修飾子」カテゴリが作成されました。

6.6.1 右辺値 (lvalue) 専用の型

const と volatile は識別子の型の一部であり、記憶クラスの一部ではありません。ただし、この部分は多くの場合、式の評価中にオブジェクトの値が取り出されるとき (正確には、lvalue が rvalue になるとき) に、型の一番上の部分から削除されます。これらの用語はプロトタイプ代入式「L=R」から来ています。この意味は、左側がオブジェクト (lvalue) を直接参照しなければならず、右側が値 (rvalue) であるだけでよいということです。したがって、lvalues である式だけが const または volatile (あるいは、その両方) で修飾できます。

6.6.2 派生型の型修飾子

型修飾子は型名と派生型を変更します。派生型は C の宣言の一部であり、何度も適用することによって、より複雑な型 (ポインタ、配列、関数、構造体、共用体) を構築できます。関数を除き、1 つまたは両方の型修飾子を使用すると、派生型の動作を変更できます。

たとえば、次を見てください。

const int five = 5;

これは、型が const int であり、値が正しいプログラムによって変更されないオブジェクトを宣言し、初期化します。キーワードの順番は C にとって重要ではありません。たとえば、次を見てください。

int const five = 5;

および

const five = 5;

この 2 つの宣言の効果は前述の宣言と同じです。

次を見てください。

const int *pci = &five;

この宣言は、型が const int へのポインタである (つまり、以前宣言されたオブジェクトを指している) オブジェクトを宣言します。ポインタ自身は修飾型を持ちません。つまり、ポインタは修飾型を指すため、プログラムの実行中に任意の int を指すように変更できます。pci を使用して、pci が指すオブジェクトを変更することはできません。このためには、次のようにキャストを使用します。

*(int *)pci = 17;

pci が実際に const オブジェクトを指す場合、このコードの動作は未定義です。

次を見てください。

extern int *const cpi;

この宣言は、プログラム内のどこかに、型が int への const ポインタである大域オブジェクトの定義があることを意味します。この場合、正しいプログラムでは cpi の値は変更されません。しかし、cpi を使用して、cpi が指すオブジェクトを変更することはできます。前述の宣言において、const が * のあとにあることに注意してください。次の 2 つの宣言の効果は同じです。

typedef int *INT_PTR;
extern const INT_PTR cpi;

前述の宣言は、次の宣言のように連結できます。この場合、オブジェクトの型は const int への const ポインタであると宣言されます。

const int *const cpci;
  

6.6.3 const は readonly を意味する

なお、キーワードとしては通常 const よりも readonly を選択するほうが便利です。このように const を解釈すると、次のような宣言は簡単に理解できます。

char *strcpy(char *, const char *);

この宣言では、2 番目のパラメータは文字値を読み取るためだけに使用され、最初のパラメータはその値が指す文字を上書きすることを意味しています。さらに、前述の例の事実に関わらず、cpi の型は const int へのポインタです。したがって、実際に型が const int で宣言されたオブジェクトを指していないかぎり、その値が指すオブジェクトの値は別の方法で変更できます。

6.6.4 const の使用例

const の 2 つの主な使用法は、コンパイル時に初期化された大きな情報テーブルが未変更であると宣言することと、ポインタパラメータが指しているオブジェクトを変更しないことを指定することです。

最初の使用法では、同じプログラムのほかの並行呼び出しが、プログラムのデータ部分を共有可能にします。つまり、データはメモリーの読み取り専用部分にあるため、この不変データを変更しようとする試みを、ある種類のメモリー保護障害で即座に検出できます。

2 番目の使用法では、実行中にメモリー障害が発生する前に、潜在的なエラーを見つけることができます。たとえば、ヌル文字を挿入できない文字列に対して、ある関数が一時的にヌル文字を挿入しようとした場合、その関数は、コンパイル時、ヌル文字を挿入できない文字列へのポインタが渡されたときに検出されます。

6.6.5 volatile は文字どおりの解釈を意味する

ここまでは、例の中でいずれも const を使用してきました。概念としてはこの方が簡単だからです。しかし、volatile はどのような意味でしょうか。volatile という言葉は「揮発性の」、つまりすぐに変わってしまうという意味を持ちます。そのためコンパイラでは、コード生成時にこのようなオブジェクトにアクセスするためのショートカットは行われません。ANSI/ISO C では、オブジェクトを volatile 修飾型として宣言するかどうかはプログラマの責任であると規定しています。

6.6.6 volatile の使用例

volatile は、通常、次の 4 つのオブジェクトに使用します。

最初の 3 つの例はすべて、特定の動作を行うオブジェクトのインスタンスです。つまり、その値は、プログラムの実行中の任意の時点で変更できます。したがって、外見上は無限ループに見える次のコードは、

flag = 1;
while (flag);

flag が volatile 修飾型を持つ間は有効な文となります。おそらく、ある非同期イベントが将来 flag をゼロに設定することもあります。volatile 修飾型を持たない場合、flag の値はループ本体内では変更されないため、コンパイルシステムによって前述のループは、完全に flag の値を無視する本当の無限ループに変更されることもあり得ます。

4 番目の例は、setjmp を呼び出す関数に対して局所的な変数を含んでいるため、より複雑です。setjmp と longjmp の動作についての細字部分には、4 番目の例に一致するオブジェクトの値は保証されないという注記があります。もっとも望ましい動作を行うためには、setjmp を呼び出す関数と longjmp を呼び出す関数の間で、longjmp がすべてのスタックフレームを検査して、保存されたレジスタ値と比較することが必要です。スタックフレームは非同期的に作成される可能性があるため、この作業はより難しくなります。

自動オブジェクトを volatile 修飾型で宣言したとき、コンパイルシステムは、プログラマが書いたものと完全に一致するコードを生成します。したがって、このような自動オブジェクトに対する最新の値は常に、レジスタではなく、メモリー内に存在します。そして、longjmp が呼び出されたときに最新であることが保証されます