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 constvolatile

6.6.1 右辺値 (lvalue) 専用の型

6.6.2 派生型の型修飾子

6.6.3 constreadonly を意味する

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.10 式のグループ化と評価

C の設計において Dennis Ritchie が行なった選択の 1 つとして、式の中で数学的に交換可能で結合可能な演算子が隣接する場合、括弧が存在する場合でも、その式を再配置する権利をコンパイラに与えました。このことは、Kernighan と Ritchie 著の『プログラミング言語 C』の付録に明示的に記載されています。しかし、ISO C は、この権利をコンパイラに与えませんでした。

この節では、前述の 2 つの C の定義間の違いを説明します。また、次のコードにおける式文を考えることによって、式の副作用、グループ化、および評価の間の区別を明らかにします。

int i, *p, f(void), g(void);
/*...*/
i = *++p + f() + g();

6.10.1 定義

式の副作用とは、メモリーへの変更と、volatile 修飾オブジェクトへのアクセスのことです。前述の式の副作用とは、ip の更新と、関数 f()g() 内に含まれる任意の副作用です。

式のグループ化とは、値をほかの値や演算子と結合させる方法です。前述の式のグループ化は、主に加算を実行する順番です。

式の評価には、その結果の値を生成するために必要なすべてが含まれます。式を評価するためには、指定したすべての副作用が以前のシーケンスポイントから次のシーケンスポイントまでの間で発生しなければならず、指定した演算が特定のグループ化で実行されなければいけません。前述の式の場合、ip の更新は、以前の文からこの式文の ; までの間に発生しなければいけません。関数への呼び出しは、以前の文からその戻り値が使用されるまでの間に、任意の順番で発生できます。特に、メモリーを更新する演算子には、演算の値が使用される前に新しい値を代入しなければならないという制約はありません。

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

前述の式では加算が数学的に交換可能で、また結合可能であるため、K&R C の再配置の権利が前述の式に適用されます。通常の括弧と実際の式のグループ化を区別するために、左右の中括弧でグループ化を示します。この式の場合、次の 3 つのグループ化が考えられます。

i = { {*++p + f()} + g() };
i = { *++p + {f() + g()} };
i = { {*++p + g()} + f() };

前述のすべてのグループ化は、K&R C の規則であれば有効です。さらに、たとえば、次のように式を書き換えた場合でも、前述のすべてのグループ化は有効です。

i = *++p + (f() + g());
i = (g() + *++p) + f();

オーバーフローによって例外が発生するか、あるいは、オーバーフローで加算と減算が逆にならないアーキテクチャー上でこの式が評価される場合、加算の 1 つがオーバーフローしたとき、前述の 3 つのグループ化の動作は異なります。

このようなアーキテクチャー上では、K&R C では、式を分割することによって強制的にグループ化するしか方法がありません。次に、前述の 3 つのグループ化を強制的に行うために式を分割した例を示します。

i = *++p; i += f(); i += g()
i = f(); i += g(); i += *++p;
i = *++p; i += g(); i += f();

6.10.3 ISO C の規則

ISO C では、数学的に交換可能で結合可能であるが、対象となるアーキテクチャー上では実際にそうではない演算を再配置することは許可されていません。したがって、ANSI/ISO C の文法の優先度と結合規則では、すべての式のグループ化が完全に記述されています。つまり、すべての式は、構文解析されるとおりにグループ化されなければいけません。前述の式は、次の方法でグループ化されます。

i = { {*++p + f()} + g() };

このコードでもなお「f()g() よりも前に呼び出されなければならない」、あるいは、「g() が呼び出されるよりも前に p が増分されなければならない」ということはありません。

ISO C では、予想外のオーバーフローが発生しないように式を分割する必要があります。

6.10.4 括弧

ISO C では、不十分な理解と不正確な表現のために、括弧の信頼性と括弧に従った評価について、間違って記述されることがしばしばあります。

ISO C の式は構文解析で指定されるグループ化を持つため、括弧は、どのように式が構文解析されるかを制御する方法としてだけ機能します。つまり、式の自然な優先度と結合規則が括弧とまったく同じ重要さを持ちます。

前述の式は、次のように書くこともできます。

i = (((*(++p)) + f()) + g());

グループ化と評価に与える影響は、括弧を使用しない場合と同じです。

6.10.5 as if 規則

K&R C の再配置規則には、いくつかの理由がありました。

ISO C 委員会は、記述される対象アーキテクチャーに適用されるときに、再配置規則は「as if」規則のインスタンスになるものであると、最終的に確信しました。ISO C の「as if」規則は、有効な C プログラムの動作を変更しないかぎり、実装が必要に応じて抽象マシン記述から離れることを一般的に許可しています。

したがって、すべてのビット単位の 2 項演算子 (シフトを除く) は任意のマシンで再配置できます。これは、このような再グループ化を確認できる方法がないためです。2 の補数を使用するマシンでオーバーフローが発生しない場合は、いくつかの理由のため、乗算または加算を含む整数式は再配置できます。

したがって、C におけるこの変更は、ほとんどの C プログラマには重要な影響を与えません。