静的解析,構成管理,MISRA-C,コードレビュー,バグトラッキング,リバースエンジニアリング
ソフトウエア開発支援ツール
  SOFTWARE SOLUTIONS
 ソフトウェア開発における品質の向上、および生産性の向上を目指して、最適な開発支援ツールを提供します。
ソフトウエア開発支援ツール > 製品紹介 > 静的解析ツール QAC > QAC の技術情報 > ホワイトペーパー > ANSI C型拡張
ホワイトペーパー


ANSI C型拡張 リチャード・スワントン
(株)東陽テクニカ
TAN sstp-9508-0015

概要

汎整数拡張の規則が、ANSI C の許可の元で変更しました。静かな変換のため、K & Rで 「符号((unsigned)」を保持していた変換は、ANSI では「値」を保持する規則に変更されました。

1. 序論

まず始めに、' 静かな変更' とは何かについて説明する必要があります。' 静かな変更' とは、言語標準において診断の原因にならない変更のことです。
なぜ診断メッセージが必要ないのか疑問に思うかもしれません。
基本的には、C 言語の方言が広まり、広まった方言が選択されたほうが良い領域で静かな変更が行われました。
ここでは静かな変更の良否の議論はしませんし、診断メッセージや選択の根拠の良否についても議論しません。

2. 値保持の規則

' 静かな変更' の中でも重要なのは、型拡張に関するものでした。 K & R では 「符号(unsigned)」 を保持する規則で型拡張していましたが、ANSI C 標準では「値」を保持する規則で型拡張します。

「符号(unsigned)」を保持して算術変換を行うプログラムは、コンパイラがワーニングを出さないまま振る舞いが異なるという影響があります。

「符号(unsigned)」を保持する規則:

2 つのうちどちらかのオペランドが符号なしの場合、両方のオペランドとも、“一番簡単に”計算できる、少なくとも大きな型のオペランドと同じ大きさの符号なしの型に拡張される。

つまり、(unsigned char型 - int 型) の計算結果は、unsigned int型になります。

「値」を保持する規則:
両方のオペランドとも、2つのオペランドの全ての値を表現できる、一番簡単に計算できる型に拡張される。

つまり、(unsigned char型 - int 型) の計算結果は、unsigned char型が int 型より狭い範囲を表現する限りは int型になります。

「符号(unsigned)」を保持する規則とは違い、目的のマシンが異なれば計算結果の型は異なります。

以下に ANSI C の 6.2.1.5 章を引用します。

「算 術型のオペランドを持つ多くの 2 項演算子は、オペランドの型変換を行い、同様の方法で結果の型を決める。型変換は、共通の型を決めるために行う。この型が結果の型にもなる。これを通常の 算術型変換(usual arithmetic conversion)と呼ぶ。通常の算術型変換の規則は、次のとおりとする。

まず、一方のオペランドが long double型をもつ場合、他方のオペランドを long double型に変換する。

そうでない場合、一方のオペランドが double型をもつならば、他方のオペランドを double型に変換する。

そうでない場合、一方のオペランドが float型をもつならば、他方のオペランドを float型に変換する。

そうでない場合、次の規則に従って汎整数拡張を両オペランドに対して行う。

一方のオペランドが unsigned long int型をもつ場合、他方のオペランドを unsigned long int型に変換する。

そうでない場合、一方のオぺランドが long int型をもち、他方のオペランドが unsigned int型をもち、更に、long intunsigned intのすべての値を表現できるなら、unsigned int型オペランドを long int型に変換する。long intunsigned intのすべての値を表現できないなら、両オペランドを unsigned long int型に変換する。

そうでない場合、一方のオペランドが long int型をもつならば、他方のオペランドを long int型に変換する。

そうでない場合、一方のオペランドが unsigned int型をもつならば、他方のオペランドを unsigned int型に変換する。

そうでない場合、両オペランドは int型をもつ。」

上記のことから分かるように、unsigned 型のオペランドが含まれている場合は、変換規則はかなり複雑です。
signed の値と unsigned の値の比較は様々な整数型のサイズに依存するので、マシン依存になるのが問題です。
例えば、int が 16 ビットで long が 32 ビッドの場合を仮定します。
このとき、int 型の 1U は signed long に拡張されるので -1L < 1U となります。しかし、-1L が unsigned long に拡張されて非常に大きな正数を示しますので -1L > 1UL となります。

2101 portable 汎整数拡張は値を保持します.: 'unsigned short'から'signed int'へ拡張されます.しかしK&R Cはここで 'unsigned int' を生成します.
2100 portable 汎整数拡張は値を保持します.: 'unsigned short'から'signed int'へ拡張されます.しかしK&R Cはここで 'unsigned int' を生成します.


上記の QA C の警告メッセージは、ANSI C標準の‘静かな'変更に対する診断メッセージを提示しています。
ソースコードを解析した結果上記2つの警告メッセージのいずれかが表示された場合、新しい拡張規則によって正しく機能するかどうか確かめるために、テストした方が良いでしょう。

3. 参考文献:

プログラミング言語 C 第2版,
Brian W. Kernighan & Dennis M. Ritchie著,石田晴久訳, 共立出版

JIS X 3010-1993 (ISO/IEC 9899-1990) プログラム言語 C

Quiet Changes, Part 2 by P. J. Plauger, The C Users Journal,March 1990

Quiet Changes, Part 1 by P. J. Plauger, The C Users Journal,February 1990


戻る