C言語

C言語:通常の算術型変換について(2)

C言語で暗黙的に行われる型変換についてまとめます。通常の算術型変換の言語仕様を紹介します。

通常の算術型変換(usual arithmetic conversion)

C90の言語仕様を紹介します。

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

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

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

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

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

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

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

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

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

JIS X 3010:1993 6.2.1.5

2項演算子の両辺のオブジェクトは、型が広いほうに型変換する、という処理になります。

昨日の記事から

昨日の記事で以下のプログラムを紹介しました。

#include <stdio.h>

int main(void)
{
	int  a = 2000000000;
	int  b = 2000000000;
	long c = 4000000000;

	printf("%ld\n", (a + b) + c);
	printf("%ld\n", a + (b + c));

	return 0;
}

この出力は以下でした。

3705032704
8000000000

9行目は、(a + b) + c を計算します。a と b は、型intをもつため、intで演算を行います。32ビット符号付き整数は、-2147483648~2147483647 の値を持つことが一般的です(2の補数)。このため、20億と20億を加えると、オーバーフローして負の値となります。このオーバーフローした値に変数cの値を加えているため、正しい結果となりません。

一方、10行目は、a + (b + c) を計算します。先に b + c を計算します。通常の算術型変換により、変数bの型がlong型に型変換されます。また、a + (b + c の結果)を演算する場合も、通常の算術型変換により変数bの型がlong型に型変換されます。このため、意図した値が出力されました。

最後に

(a + b) + c と a + (b + c) の計算結果が異なるのは、不思議な気がするのではないでしょうか。言語仕様を把握することにより、うまく動かなかったプログラムのメカニズムが分かりました。

C言語を使いこなしていきましょう!

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA