11

C実装(たとえば、x86 Cコンパイラ)USHRT_MAX = 65535INT_MAX = 2147483647。では、次のステートメントは明確に定義されていますか?

unsigned short product = USHRT_MAX * USHRT_MAX;

C99標準の次のように、両方のオペランドがに昇格されintintのすべての可能な値を表すことができるunsigned shortため)、したがって、オーバーフローが発生するため、結果は明確に定義されません(65535 ^ 2 = 4294836225 > 2147483647)、つまり、の値productは明確に定義された:

6.3.1.1-1

intが元の型のすべての値を表すことができる場合、値はintに変換されます。それ以外の場合は、unsignedintに変換されます。これらは整数プロモーションと呼ばれます。(48)他のすべてのタイプは整数プロモーションによって変更されません。

48)整数拡張は、通常の算術変換の一部として、特定の引数式、単項+、-、および〜演算子のオペランド、およびそれぞれによって指定されたシフト演算子の両方のオペランドにのみ適用されます。副次句。

ただし、以下によれば、符号なしオペランドを含む計算はオーバーフローしないため、結果は明確に定義されています。

6.2.5-9

符号付き整数型の非負の値の範囲は、対応する符号なし整数型のサブ範囲であり、各型での同じ値の表現は同じです。(31)符号なし整数を含む計算は、次のような結果になるため、オーバーフローすることはありません。結果の符号なし整数型で表すことはできませんが、結果の型で表すことができる最大値より1大きい数を法として減らされます。

product前述のステートメントの変数には明確に定義された値がありますか?

編集:次の場合はどうなりますか?

unsigned short lhs = USHRT_MAX;
unsigned short rhs = USHRT_MAX;
unsigned short product = lhs * rhs;
4

2 に答える 2

4

プロモーションが勝ちます。

USHRT_MAX定数などについてセクション5.2.4.2.1は次のように述べています。

#if以下に示す値は、前処理ディレクティブでの使用に適した定数式に置き換える必要があります。さらに、とを除いてCHAR_BITMB_LEN_MAX以下は、整数昇格に従って変換された対応するタイプのオブジェクトである式と同じタイプの式に置き換えられるものとします

したがって、乗算はsで行われ、符号なしオペランドは含まれません。明確に、。の場合、符号なしオペランドを含む演算を取得するためintの適合方法はありません。したがって、オーバーフローが発生し、未定義の動作が発生します。USHRT_MAXUSHRT_MAX < INT_MAX

追加された質問について

編集:次の場合はどうなりますか?

unsigned short lhs = USHRT_MAX;
unsigned short rhs = USHRT_MAX;
unsigned short product = lhs * rhs;

それはまったく同じ状況です。のオペランドは*整数拡張の対象であり、タイプのすべての値はとの値の仮定によってsunsigned shortとして表すことができるため、乗算はsで行われ、指定された値でオーバーフローします。intUSHRT_MAXINT_MAXint

符号なしオペランドで乗算を実行するには、少なくとも1つのオペランドをintoerderでプロモートされていない符号なしタイプに変換する必要があります。

于 2013-03-27T10:35:54.733 に答える
1

乗算演算子が適用されるまでに、そのオペランドはすでに符号付き整数になっているため、UBを取得します(int最初に発生するように昇格するため)。

これで回避できます:

unsigned short product = USHRT_MAX * (unsigned)USHRT_MAX;

(unsigned)some_integer署名されていない証拠:

#include <stdio.h>

int main(void)
{
  printf("1u * (-1) = %f\n", (((unsigned)1) * (-1)) + 0.0);
  printf("1 * (-1) = %f\n", (1 * (-1)) + 0.0);
  return 0;
}

出力(ideone):

1u * (-1) = 4294967295.000000
1 * (-1) = -1.000000

良いキャッチ、ところで。

于 2013-03-27T10:35:22.957 に答える