Ist numeric_limits <int> :: is_modulo logisch widersprüchlich?
Imeine andere Frage, das Thema vonstd::numeric_limits<int>::is_modulo
ergab sich. Aber je mehr ich darüber nachdenke, desto mehr scheint etwas mit der Spezifikation oder mit GCC oder beiden nicht zu stimmen.
Lassen Sie mich mit einem Code beginnen:
#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";
}
Wenn ich das mit kompiliereg++ -O3 -std=c++11
(x86_64 GCC 4.7.2) erzeugt die folgende Ausgabe:
1 -2147483648 1
Das ist,is_modulo
ist wahr, eins plusINT_MAX
ist negativ und eins plusINT_MAX
ist größer alsINT_MAX
.
Wenn Sie der Typ sind, der eine realistische Chance hat, diese Frage zu beantworten, wissen Sie bereits, was hier passiert ist. Die C ++ - Spezifikation besagt, dass der Ganzzahlüberlauf Undefiniertes Verhalten ist. Der Compiler darf davon ausgehen, dass Sie dies nicht tun. daher das Argument zux+1
kann nicht seinINT_MAX
; Daher kann (und wird) der Compiler das kompilierentest
Funktion, um zurückzukehrentrue
bedingungslos. So weit, ist es gut.
DieC ++ 11 spec sagt auch (18.3.2.4 Absätze 60-61):
static constexpr is_modulo;
True, wenn der Typ modulo.222 ist. Ein Typ ist modulo if für jede Operation, die einbezieht+
, -
, oder*
auf Werten dieses Typs, deren Ergebnis außerhalb des Bereichs liegen würde[min(),max()]
weicht der zurückgegebene Wert vom wahren Wert um ein ganzzahliges Vielfaches von abmax() - min() + 1
.
Bei den meisten Maschinen ist dies der Fallfalse
für schwimmende Typen,true
für vorzeichenlose ganze Zahlen undtrue
für vorzeichenbehaftete ganze Zahlen.
Beachten Sie, dass Abschnitt 5 Absatz (4) weiterhin lautet: "Wenn während der Auswertung eines Ausdrucks das Ergebnis nicht mathematisch definiert ist oder nicht im Bereich der darstellbaren Werte für seinen Typ liegt, ist das Verhalten undefiniert." Es gibt keine Erwähnung vonis_modulo == true
eine Ausnahme erstellen.
Daher scheint mir der Standard logisch widersprüchlich zu sein, da ein Ganzzahlüberlauf nicht gleichzeitig definiert und undefiniert werden kann. Zumindest ist GCC nicht konform, weil es dies getan hatis_modulo
wietrue
Auch wenn die vorzeichenbehaftete Arithmetik mit Sicherheit kein Problem darstellt.
Ist der Standard Buggy? Ist das GCC nicht konform? Vermisse ich etwas?