Dlaczego wyrażenie (int) + 1e10 nie daje -2147483648, jak opisuje CSAPP? [duplikować]
Czytam CS: APP (zbiór x86-64 / podręcznik niskiego poziomu) i wspomina o:
Od
float
lubdouble
doint
wartość zostanie zaokrąglona w kierunku zera. Na przykład1.999
zostanie przekonwertowany na1
, podczas gdy−1.999
zostanie przekonwertowany na−1.
Ponadto wartość może się przepełnić. Normy C nie określają stałego wyniku dla tego przypadku. Mikroprocesory kompatybilne z Intel wyznaczają wzór bitowy [10… 00] (TMinw
dla rozmiaru słowaw
) jako nieokreśloną wartość całkowitą. Każda konwersja ze zmiennoprzecinkowej na liczbę całkowitą, która nie może przypisać rozsądnego przybliżenia liczby całkowitej, daje tę wartość. W ten sposób wyrażenie(int) +1e10
daje-2147483648
, generując ujemną wartość z dodatniej.
O jakich mikroprocesorach jest mowa w tym miejscu? x86
architektura obejmująca serię AMD?
W każdym razie mam Intel i5 z 64-bitową maszyną Win10 i próbowałem pod Visual Studio:
#include <iostream>
using namespace std;
int main() {
int b = (int)+1e10;
cout << b << endl;
}
i otrzymuje 1410065408
jako wyjście.
Również próbowałem int32_t
i 1410065408
też dostaje .
Więc dlaczego nie mogę mieć wynik -2147483648
, który jest [10 ... 00]
jak książka opisuje?
Odpowiedzi
Nawet jeśli używany procesor ma „Każda konwersja z wartości zmiennoprzecinkowej na liczbę całkowitą, która nie może przypisać rozsądnego przybliżenia liczby całkowitej, daje tę wartość”, kompilator nie musi tego przestrzegać, ponieważ może użyć innego kodu, aby osiągnąć cel.
W szczególności wartości, które można określić w czasie kompilacji, takie jak, some_32_bit_int = (int)+1e10;
mogą otrzymać wartość podobną some_32_bit_int = 10000000000 & 0xFFFFFFFF;
lub 1410065408
całkowicie niezależną od procesora.
Jeśli wartość części całkowitej nie może być reprezentowana przez typ całkowity, zachowanie jest niezdefiniowane.
C17dr § 6.3.1.4 1
Książka opisuje procesor, a nie kompilator.