JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
Oracle Solaris Studio 12.3: C ユーザーガイド     Oracle Solaris Studio 12.3 Information Library (日本語)
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 例: キャストの使用

6.4.4 例: 同じ結果、警告なし

6.4.5 整数定数

6.4.6 例: 整数定数

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.7 複数バイト文字とワイド文字

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

6.7.2 符号化の種類

6.7.3 ワイド文字

6.7.4 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.  Oracle Solaris Studio C: K&R C と ISO C の違い

索引

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

1990 ISO C 規格の「Rationale」(論理的根拠) 節に、次のような情報があります。「QUIET CHANGE」(メッセージなしの変更)。符号なし保存演算変換に依存するプログラムは、おそらくはメッセージを発行せずに、異なる動作を行います。この変更は、現在広く行われている慣習に対して委員会が行なったもっとも重大な変更であると考えられます。

この節では、この変更がコーディングにどのように影響するかを説明します。

6.4.1 若干の背景となる歴史

『プログラミング言語 C』の最初のエディションでは、unsigned は正確に 1 つの型を指定しており、unsigned char、unsigned short、unsigned long はありませんでした。ほとんどの C コンパイラにはそれからまもなく、これらが追加されました。一部のコンパイラは unsigned long を実装せず、残りの 2 つを含んでいました。当然、式の中でこれらの新しい型がほかの型と併用されている場合、実装によって異なる型拡張規則が適用されました。

ほとんどの C コンパイラでは、より単純な規則である「符号なし保持」が使用されています。符号なし型を拡張する必要があるときは符号なし型に拡張され、符号なし型が符号付き型と混在するときは結果は符号なし型です。

ISO C で定義されるもう一方の規則は、「値の保持」と呼ばれ、結果の型はオペランドの型の相対的なサイズによって異なります。unsigned char または unsigned short が拡張されるとき、int がより小さい型の値をすべて表現できる大きさである場合は、結果の型は int です。それ以外の場合、結果の型は unsigned int です。この「値の保持」規則は、ほとんどの式に予期されない演算結果になることは少なくなります。

6.4.2 コンパイルの動作

移行モードまたは ISO モード (-Xt または -Xs) でのみ、ISO C コンパイラは符号なし保持拡張を使用します。ほかの 2 つのモード、準拠 (–Xc) と ISO (–Xa) では、値保持拡張規則が使用されます。

6.4.3 例: キャストの使用

次のコードでは、unsigned char が int より小さいと仮定します。

int f(void)
{
    int i = -2;
    unsigned char uc = 1;

   return (i + uc) < 17;
}

このコードは、-xtransition オプションを使用したときに、コンパイラが次の警告を発行する原因になります。

line 6: warning: semantics of "<" change in ISO C; use explicit cast

加算の結果の型は int (値保持) または unsigned int (符号なし保存) です。しかし、どちらの場合でもビットパターンは同じです。2 の補数を使用するマシンでは、次のようになります。

    i:       111...110 (-2)
+   uc:      000...001 ( 1)
===================
        111...111 (-1 or UINT_MAX)

このビット表現は、int では -1 に対応し、unsigned int では UINT_MAX に対応します。したがって、結果の型が int の場合、符号付きの比較が使用され、「小さい」のテストは真になります。結果の型が unsigned int の場合、符号なしの比較が使用され、「小さい」のテストは偽になります。

キャストの加算を使用すると、2 つの動作のうち、どちらを希望するかを指定できます。

value preserving:
    (i + (int)uc) < 17
unsigned preserving:
    (i + (unsigned int)uc) < 17

異なるコンパイラが同じコードに対して異なる意味を選択したため、この式は曖昧になる可能性があります。キャストの加算を使用することにより、コードが読みやすくなると同時に、警告メッセージも発行されなくなります。

同じ動作が、ビットフィールド値の拡張にも適用されます。ISO C では、int または unsigned int ビットフィールド内のビットの数が int 中のビットの数よりも少ない場合、拡張される型は int です。それ以外の場合、拡張される型は unsigned int です。ほとんどの古い C コンパイラでは、明示的な符号なしビットフィールドの場合、拡張される型は unsigned int です。それ以外の場合は int です。

この場合も、キャストを使用することにより、曖昧になることを防ぐことができます。

6.4.4 例: 同じ結果、警告なし

次のコードでは、unsigned short と unsigned char の両方が int よりも狭いと仮定します。

int f(void)
{
    unsigned short us;
    unsigned char uc;
    return uc < us;
}

この例では、2 つの自動変数は int または unsigned int のどちらかに拡張されます。したがって、比較対象は符号なしになることも、符号付きになることもあります。しかし、どちらを選んでも結果は同じなので、警告は発行されません。

6.4.5 整数定数

式と同様に、ある整数定数の型の規則も変更されました。K&R C では、接尾辞なしの 10 進定数の型が int になるのは、その値が int に収まる場合だけでした。接尾辞なしの 8 進数定数または 16 進数定数の型が int になるのは、その値が unsigned int に収まる場合だけでした。それ以外の場合、整数定数の型は long でした。したがって、値が結果の型に収まらないことがありました。1990 ISO/IEC C 規格では、定数の型は、次のリストのうち、値を格納できる最初の型となります。

-xtransition オプションを使用するとき、関係する定数の型規則によって式の動作が異なる可能性がある場合は ISO C コンパイラは式について警告します。古い整数定数型規則が使用されるのは、移行モードだけです。ISO モードと準拠モードでは新しい規則が使用されます。


注 - 接尾辞なしの 10 進定数の型規則は、1999 ISO C 規格に従って変更されています。「2.1.1 整数定数」を参照してください。


6.4.6 例: 整数定数

次のコードでは、int が 16 ビットであると仮定します。

int f(void)
{
    int i = 0;

    return i > 0xffff;
}

16 進定数の型は int (2 の補数を使用するマシン上で - 1 の値を持つ) または unsigned int (65535 の値を持つ) のどちらかです。比較結果は、ANSI 以前モード (-Xs) と移行モード (-Xt) では真で、ANSI モード (-Xa) と準拠モード (-Xc) では偽です。

この場合も、キャストを適切に使用することにより、コードが読みやすくなり、警告も発行されなくなります。

-Xt, -Xs modes:
    i > (int)0xffff

-Xa, -Xc modes:
    i > (unsigned int)0xffff
       or
    i > 0xffffU

接尾辞 U 文字は ISO C の新しい機能であるため、古いコンパイラではおそらくエラーメッセージが生成されます。