0

大きな整数 (unsigned long long) を扱っており、オーバーフロー状態を防ぐ必要があります。実際に例外があるかどうかに関係なく、コードは例外をスローします。

try
{
    unsigned long long y = std::numeric_limits<unsigned long long>::max() - 2;
    unsigned long long z = 1;
    int size = - 1;
    if((y+z) ^ y < 0) //If y+z causes overflow its sign will be changed => y and (y+z) will have opposite signs
        throw std::overflow_error("overflow of y+z");
    //int* myarray= new int[size]; VS Debug Library catches it earlier than catch()
    printf("%d\n", y*(y+z));
}
catch(exception& e)
{
    cout << e.what() << endl;
}

これはすでに最大のデータ型 (64 ビット) であるため、より大きなデータ型に昇格する余地はありません。

新しいコード:

try
{
    unsigned long long int y = std::numeric_limits<unsigned long long int>::max() - 2;
    unsigned long long int z = std::numeric_limits<unsigned long long int>::max() / 2;
    unsigned long long delta = std::numeric_limits<unsigned long long int>::max() - y;
    int size = - 1;
    if(z > delta) //If y+z causes overflow its sign will be changed => y and (y+z) will have opposite signs
        throw std::overflow_error("overflow of y+z");
    //int* myarray= new int[size]; VS Debug Library catches it earlier than catch()
    printf("%d\n", (y+z));
}
catch(exception& e)
{
    cout << e.what() << endl;
}
4

2 に答える 2

3

y < 0常に false になり、 xor 0 は常にそのようになります (<それよりも高い優先順位で評価されることを見逃しました^か?)。

したがって、x + ymod<the max value>がたまたま 0 に等しくない限り、スローします (特定の入力を工夫しない限り、実際には常にスローするように見えます)。

おそらく、あなたが意図したことは次のようなものでした:if((std::numeric_limits<unsigned long long>::max() - y) < z) throw ...;

于 2015-04-21T17:07:56.463 に答える
2

2 つの問題があります。主なものは演算子の優先順位です:<よりも高いです^。これは、すべての警告を有効にしてコンパイルする大きな理由です。gcc と clang の両方で、この式に関する警告が表示され、括弧が提案されるからです。

コンパイラによって評価される式は、実際には次のようになります。

if ( (y+z) ^ (y < 0) )

y < 0として評価されるため0、次のようになります。

if (y+z)

これは明らかにtrueです。ただし、括弧が正しい場合でも、次のようになります。

if (((y+z) ^ y) < 0) { ... }

その表現は自明falseです。unsigned long longとして評価されることのない型がまだあり< 0ます。

于 2015-04-21T17:08:26.793 に答える