2015-05-19 25 views
6

Niepodpisana int może zawierać tylko 32 bity danych. Dlaczego kompilator nie daje błędu, gdy przypisuję mu większą wartość niż to, co może on pomieścić?Dlaczego ten unsigned int zawiera więcej danych niż ma w pamięci?

Próbowałem innych różnych wartości i nadal nie daje błędu.

int main() 
{ 
    unsigned int mem = 0x89678456543454345934; 
    cout << mem; 

    return 0; 
} 
+2

Ponieważ zachowanie niepodpisanego końca całkowitego jest dobrze zdefiniowane. Czy też pytasz, dlaczego tak jest, dlaczego projektanci C++ nie popełnili błędu? – juanchopanza

+4

FWIW prawdopodobnie zwiększysz swój poziom ostrzeżenia. –

+0

tak, dlaczego to jest – wazeeer

Odpowiedz

12

To dlatego, że 0x89678456543454345934 jest większa niż std::numeric_limits<unsigned_int>::max(). Jednak typy unsigned zawijają się wokół ich maksymalnej wartości, więc jeśli prawa strona jest reprezentowana przez typ całkowity, masz dobrze określone zachowanie. W takim przypadku wynikiem jest 0x89678456543454345934 mod std::numeric_limits<unsigned_int>::max.

EDIT

Po prawej stronie swojego przydziału jest integer literal. Aby go reprezentować, kompilator używa pierwszego typu (order wrt jego size), w którym może zmieścić się liczba całkowita. Jeśli nie ma takiego typu, to program jest źle sformułowany. Wartość dziesiętną swojej stałej jest:

648873758694578209446196L 

Na moim komputerze, zarówno dla brzękiem ++ i g ++ std::numeric_limits<unsigned long long>::max() jest 18446744073709551615, która jest mniejsza niż stała. Wygląda na to, że twój program jest źle sformułowany, chyba że kompilator używa więcej niż 64 bitów do reprezentowania unsigned long long, co bardzo wątpię. Jak @juanchopanza zauważył, dzyń ++ odmawia skompilować kod, z błędem

error: integer constant is larger than the largest unsigned integer type

g ++ jednak idzie do przodu i kompiluje go, emitując jedynie ostrzeżenie

warning: large integer implicitly truncated to unsigned type

Ostrzeżenie jest dość mylące, gdyż odnosi się do prawej strony, a nie do dalszej konwersji na unsigned int, za które można dostać

warning: large integer implicitly truncated to unsigned type [-Woverflow]

na moim komputerze std::numeric_limits<unsigned int>::max() jest 4294967295, a zatem 648873758694578209446196L % 4294967295 jest 3633002191L. Jednak po uruchomieniu programu otrzymuję 1412716852. Dzieje się tak, ponieważ program jest źle sformułowany i niestety kompilator nie wysyła błędu (nie jest to wymagane przez standard), ale tylko ostrzeżenie.

+2

Clang daje mi bardziej istotny błąd: 'error: integer literal jest zbyt duży, aby być reprezentowanym w dowolnym typie całkowitym ' – juanchopanza

+0

yup g ++ zmienia wartości mem z 9535901844731353396 na 1412716852 –