2

私は Stroustrup の本「The C++ Programming Language 4th edition」を読んでいて、割り当てのオーバーフローに関して 3 つの質問があります (特に、本が示すように、signed/unsigned char に対して)。まず、標準の 5/4 パラグラフによると:

式の評価中に、結果が数学的に定義されていないか、その型の表現可能な値の範囲内にない場合、動作は undefinedです。

(宛先変数が符号なしの場合を除きます - そのような場合、結果は明確に定義されます)。しかし、この定義は割り当てにも関係しますか?

私の意見では、この本には多くの反対の声明があり、すべて第6章にあります.最初のものは前述の段落に対応していますが、次のコメントはそうではありません:

3 つのタイプの変数は、char相互に自由に割り当てることができます。ただし、大きすぎる値を a に代入することsigned charはまだ定義されていません。例えば:

void g(char c, signed char sc, unsigned char uc)
{
    c = 255; //implementation-defined if plain chars are signed and have 8 bits
    c = sc; //OK
    c = uc; //implementation-defined if plain chars are signed and if uc's value is too large
    sc = uc; //implementation-defined if uc's value is too large
    uc = sc; //OK: conversion to unsigned
    sc = c; //implementation-defined if plain chars are unsigned and if c's value is too large
    uc = c; //OK: conversion to unsigned
}

最初の質問: 大きすぎる値を割り当てることは UB であるため、なぜコメントはそれが実装定義であると言っているのですか?

次に、次の例があります。

具体的には、acharが 8 ビットであると仮定します。

signed char sc = -160;
unsigned char uc = sc; //uc == 116 (because 256-160==116)
cout << uc; //print 't'

2 番目の質問: 最初の割り当てがおそらく UB であるという事実は別として、著者が 116 を導き出すために正確に使用した公式は何ですか? 私のテストでucは、96 の値を取得しました。

そして最後の引用:

整数は別の整数型に変換できます。宛先が の場合signed、宛先タイプで表現できる場合、値は変更されません。それ以外の場合、値は実装定義です。

signed char sc = 1023; //implementation-defined

妥当な結果は 127 と -1 です。

3 番目の質問: 繰り返しますが、これが以前に UB について言われたことに反するという事実は別として、なぜ可能な結果が 127 と -1 になるのでしょうか? 1 の補数と 2 の補数に関係があると思いますが、具体的にどのような公式が使われているのでしょうか?

4

1 に答える 1