Czy limity liczbowe <int> :: is_modulo są logicznie sprzeczne?
Winne pytanie, tematstd::numeric_limits<int>::is_modulo
podszedł. Ale im więcej o tym myślę, tym bardziej wydaje się, że coś jest nie tak ze specyfikacją lub GCC lub obydwoma.
Zacznę od kodu:
#include <limits>
#include <iostream>
bool test(int x)
{
return x+1 > x;
}
int main(int argc, char *argv[])
{
int big = std::numeric_limits<int>::max();
std::cout << std::numeric_limits<int>::is_modulo << " ";
std::cout << big+1 << " ";
std::cout << test(big) << "\n";
}
Kiedy to kompilujęg++ -O3 -std=c++11
(x86_64 GCC 4.7.2), generuje następujące dane wyjściowe:
1 -2147483648 1
To jest,is_modulo
to prawda, jeden plusINT_MAX
jest ujemny i jeden plusINT_MAX
jest większy niżINT_MAX
.
Jeśli jesteś osobą, która ma realistyczną szansę na odpowiedź na to pytanie, już wiesz, co się tutaj stało. Specyfikacja C ++ mówi, że przekroczenie liczby całkowitej to Niezdefiniowane zachowanie; kompilator może założyć, że tego nie robisz; dlatego argument dox+1
nie może byćINT_MAX
; dlatego kompilator może (i będzie) skompilowałtest
funkcja do powrotutrue
bezwarunkowo. Jak na razie dobrze.
JednakżeSpecyfikacja C ++ 11 również mówi (18.3.2.4 paragrafy 60-61):
static constexpr is_modulo;
Prawda, jeśli typ to modulo.222 Typ jest modulo if, dla dowolnej operacji z udziałem+
, -
lub*
na wartościach tego typu, których wynik nie mieści się w zakresie[min(),max()]
, zwracana wartość różni się od wartości prawdziwej o wielokrotność liczby całkowitejmax() - min() + 1
.
Na większości maszyn takfalse
dla typów pływającychtrue
dla liczb całkowitych bez znaku itrue
dla liczb całkowitych podpisanych.
Zwróć uwagę, że sekcja 5 akapit (4) wciąż brzmi: „Jeśli podczas oceny wyrażenia wynik nie jest matematycznie zdefiniowany lub nie mieści się w zakresie wartości reprezentowalnych dla jego typu, zachowanie jest niezdefiniowane”. Nie ma wzmianki ois_modulo == true
tworzenie wyjątku.
Wygląda więc na to, że standard jest logicznie sprzeczny, ponieważ przekroczenie liczby całkowitej nie może być jednocześnie zdefiniowane i niezdefiniowane. A przynajmniej GCC jest niezgodne, ponieważ mais_modulo
tak jaktrue
mimo że podpisana arytmetyka z pewnością nie zawija się.
Czy standardowy buggy? Czy GCC jest niezgodny? Czy czegoś mi brakuje?