Binarne operatory arytmetyczne wykonają usual arithmetic conversions na swoich operandach w celu dostosowania ich do wspólnego typu.
W przypadku i1
, i3
i i5
wspólna typu będzie unsigned int a więc wynik będzie również unsigned int. Niepodpisane liczby będą owijały się za pomocą arytmetyki modulo, więc odjęcie nieco większej, niepodpisanej wartości spowoduje, że liczba zbliżona do unsigned int max, która nie może być reprezentowana przez int.
Tak więc w przypadku i1
otrzymujemy zdefiniowaną implementację, ponieważ wartość nie może być reprezentowana. W przypadku i3
podzielenie przez 2
przenosi niepodpisaną wartość z powrotem do zakresu int, a więc kończymy na dużej wartości int po konwersji.
Odpowiednie sekcje z projektu standardowego C++ są następujące. Sekcja 5.7
[expr.add]:
operatorów dodatków + i - grupa od lewej do prawej. Typowe konwersje arytmetyczne są wykonywane dla argumentów typu arytmetycznego lub wyliczeniowego.
Zwykłe arytmetyczne konwersje są ujęte w sekcji 5
i mówi:
wielu operatorów binarnych, które oczekują argumentów arytmetyki lub wyliczenie typu konwersji przyczyna i dają rodzaje wynikowych w podobny sposób. Celem jest uzyskanie wspólnego typu, który jest także typem wyniku. Ten wzór nazywa zwykłe konwersje arytmetyczne, które są zdefiniowane w następujący sposób:
[...]
- W przeciwnym razie, jeśli operand że ma całkowitą bez znaku typu ma rangi większa lub równa pozycja typu drugiego operandu, operand z typem liczby całkowitej ze znakiem jest konwertowany na typ argumentu z bez znaku typu całkowitoliczbowego.
i konwersji z wartości, która nie może być reprezentowane przez podpisany typu punkt 4.7
[conv.integral]:
Jeżeli typ docelowy jest podpisany wartość pozostaje niezmieniony, jeśli może być reprezentowany w typie miejsca docelowego (i szerokość pola bitowego); w przeciwnym razie wartość jest definiowana przez implementację.
liczb całkowitych bez znaku i wypełnia przekrój modulo arytmetyczną 3.9.1
[basic.fundamental]:
liczby całkowite powinien stosować prawa arytmetyki modulo 2n, gdzie n oznacza liczbę bitów wartości reprezentacja tej konkretnej wielkości integer.48
_Nawiasem mówiąc, przypisanie tej wartości do i1 jest niezdefiniowanym zachowaniem_ Czy jesteś tego pewien? Nauczyłem, że konwersja z unsigned int na int sygnowane jest dobrze zdefiniowana dla wszystkich wartości unsigned int. – rozina
Tutaj nie ma przepełnionego liczby całkowitej ze znakiem. Istnieją konwersje. Zobacz [conv.integral] (http://eel.is/c++draft/conv.integral). – Sebivor
@rozina: Huh, nigdy wcześniej nie widziałem, że nawrócenie działa inaczej pod tym względem. Naprawiono – Hurkyl