1. ホーム
  2. c++

[解決済み] 8ビット整数から8ビットより大きな値を得るにはどうしたらよいですか?

2022-08-31 20:53:29

質問

私は、この小さな宝石の背後に隠れている非常に厄介なバグを突き止めました。C++ 仕様では、符号付きオーバーフローは未定義の動作であることは承知していますが、オーバーフローが発生するのは、値がビット幅 sizeof(int) . 私が理解しているように char である限り、未定義の動作になることはないはずです。 sizeof(char) < sizeof(int) . しかし、それでは c 不可能 の値を取得します。8 ビット整数として、どのように c はそのビット幅より大きな値を保持できるのでしょうか?

コード

// Compiled with gcc-4.7.2
#include <cstdio>
#include <stdint.h>
#include <climits>

int main()
{
   int8_t c = 0;
   printf("SCHAR_MIN: %i\n", SCHAR_MIN);
   printf("SCHAR_MAX: %i\n", SCHAR_MAX);

   for (int32_t i = 0; i <= 300; i++)
      printf("c: %i\n", c--);

   printf("c: %i\n", c);

   return 0;
}

出力

SCHAR_MIN: -128
SCHAR_MAX: 127
c: 0
c: -1
c: -2
c: -3
...
c: -127
c: -128  // <= The next value should still be an 8-bit value.
c: -129  // <= What? That's more than 8 bits!
c: -130  // <= Uh...
c: -131
...
c: -297
c: -298  // <= Getting ridiculous now.
c: -299
c: -300
c: -45   // <= ..........

ideoneでチェックする。

どのように解決するのですか?

コンパイラのバグです。

未定義の動作のために不可能な結果を得ることは正当な結果ですが、実際にはあなたのコードに未定義の動作はありません。起こっているのは、コンパイラが が考えていることです。 と考え、それに応じて最適化しているのです。

もし c が定義されている場合 int8_t であり int8_t に昇格します。 int となり、次に c-- は減算を行うことになっています c - 1int に変換し、その結果を int8_t . での引き算は int の引き算はオーバーフローせず、範囲外の積分値を別の積分型に変換することは有効です。変換先の型が符号付きの場合、結果は実装で定義されますが、変換先の型に対して有効な値である必要があります。(そして、宛先の型が符号なしであれば、結果はよく定義されていますが、それはここでは適用されません)。