Chcę wiedzieć, kiedy powinienem rzucać. Jakie są niejawne reguły konwersji typów w C ++ podczas dodawania, mnożenia itp. Na przykład
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
i tak dalej...
Czy wyrażenie zawsze będzie oceniane jako dokładniejszy typ? Czy zasady różnią się w przypadku języka Java? Proszę, popraw mnie, jeśli źle sformułowałem to pytanie.
^
XOR.Odpowiedzi:
W C ++ operatory (dla typów POD) zawsze działają na obiektach tego samego typu.
Tak więc, jeśli nie są takie same, jeden zostanie awansowany, aby pasował do drugiego.
Typ wyniku operacji jest taki sam jak operandy (po konwersji).
Uwaga. Minimalny rozmiar operacji to
int
. Tak więcshort
/char
są promowaneint
przed wykonaniem operacji.We wszystkich twoich wyrażeniach
int
jest promowany do afloat
przed wykonaniem operacji. Wynikiem operacji jest plikfloat
.źródło
char
typu. Jeśli wartośćchar + char
jest przypisana do achar
, to może po prostu wykonać arytmetykęchar
i na przykład zawijać. Ale jeśli wynik jest przypisany doint
, musi wykonać arytmetykę w typie wystarczająco dużym, aby uzyskać poprawny wynik, gdy jest większy niżCHAR_MAX
.((int) 4) - ((unsigned int) 5)
spowoduje, że4294967295
dla 32-bitowych int i 32-bitowych liczb int bez znaku.Operacje arytmetyczne obejmujące
float
wyniki wfloat
.Aby uzyskać bardziej szczegółową odpowiedź. Zobacz, co mówi sekcja §5 / 9 ze standardu C ++
źródło
double
anilong double
.long long
aunsigned long
nie tutaj.float
nie ma wystarczającej liczby bitów w mantysie (24 bity dla IEEE-754 ) dla 32-bitowegoint
, więc może wystąpić utrata danych. Wersja 64-bitowadouble
powinna wystarczyć.Ponieważ inne odpowiedzi nie mówią o regułach w C ++ 11, oto jedna. Ze standardu C ++ 11 (szkic n3337) §5 / 9 (podkreślono różnicę):
Zobacz tutaj listę, która jest często aktualizowana.
źródło
Ta odpowiedź jest w dużej mierze skierowana na komentarz @ RafałDowgird:
Należy pamiętać, że w standardzie C ++ obowiązuje niezwykle ważna zasada „as-if”. Patrz sekcja 1.8: Wykonanie programu:
Kompilator nie może ustawić
int
8-bitowego rozmiaru, nawet jeśli byłby najszybszy, ponieważ standard wymaga 16-bitowego minimumint
.Dlatego w przypadku teoretycznego komputera z superszybkimi 8-bitowymi operacjami, niejawna awans do
int
arytmetyki może mieć znaczenie. Jednak w przypadku wielu operacji nie można stwierdzić, czy kompilator faktycznie wykonał operacje z dokładnością an,int
a następnie przekonwertował je na a,char
aby przechowywać w zmiennej, czy też operacje były przez cały czas wykonywane w postaci znaku.Weźmy na przykład pod uwagę
unsigned char = unsigned char + unsigned char + unsigned char
, gdzie dodawanie byłoby przepełnione (przyjmijmy wartość 200 dla każdego). Jeśli awansujesz naint
, dostaniesz 600, które następnie zostanie pośrednio rzucone w dół na anunsigned char
, co zawinie modulo 256, dając w ten sposób końcowy wynik 88. Jeśli nie zrobiłeś takich promocji, musiałbyś zawijać między pierwszymi dwa dodatki, co zmniejszyłoby problem z200 + 200 + 200
do144 + 200
, czyli 344, co redukuje do 88. Innymi słowy, program nie zna różnicy, więc kompilator może zignorować polecenie wykonania operacji pośrednich,int
jeśli operandy mają niższy ranking niżint
.Dotyczy to ogólnie dodawania, odejmowania i mnożenia. Generalnie nie jest to prawdą w przypadku dzielenia lub modułu.
źródło
Jeśli wykluczysz typy bez znaku, istnieje uporządkowana hierarchia: signed char, short, int, long, long long, float, double, long double. Po pierwsze, wszystko, co znajduje się przed int w powyższym, zostanie przekonwertowane na int. Następnie, w operacji binarnej, typ o niższej randze zostanie przekonwertowany na wyższy, a wyniki będą typem wyższego. (Zauważysz, że z hierarchii za każdym razem, gdy zaangażowany jest typ zmiennoprzecinkowy i typ całkowity, typ całkowity zostanie przekonwertowany na typ zmiennoprzecinkowy).
Unsigned nieco komplikuje sprawę: zaburza ranking, a część rankingu zostaje zdefiniowana jako implementacja. Z tego powodu najlepiej nie mieszać ze znakiem i bez znaku w tym samym wyrażeniu. (Wydaje się, że większość ekspertów C ++ unika unsigned, chyba że w grę wchodzą operacje bitowe. Tak przynajmniej zaleca Stroustrup).
źródło
int
liczby, która nigdy nie musi być ujemna, jest całkowitym zmarnowaniem pełnych 50% dostępnego zakresu. Na pewno nie jestem Stroustrupem, ale używamunsigned
domyślnie isigned
tylko wtedy, gdy mam powód.bool in_order(vector<T> vec) { for ( int i = 0; i < size() - 1; ++i) { if (vec[i + 1] < vec[i]) return false; } return true;
a wtedy zirytowałbyś się, gdyby doszło do awarii dla pustych wektorów, ponieważ size () - 1 zwraca 18446744073709551615.Moje rozwiązanie do problemu dostał Waszyngton (zła odpowiedź), a potem zmienił jeden
int
dolong long int
i dał AC (zaakceptować) . Wcześniej próbowałem to zrobićlong long int += int * int
, a po poprawieniu tego nalong long int += long long int * int
. Google, które wymyśliłem,1. Konwersje arytmetyczne
Warunki konwersji typu:
Warunki spełnione ---> Konwersja
Każdy operand jest typu long double . ---> Inny operand jest konwertowany na typ long double .
Warunek poprzedzający nie został spełniony, a jeden z operandów jest typu double . ---> Inny operand jest konwertowany na typ double .
Warunki poprzedzające nie zostały spełnione, a jeden z operandów jest typu float . ---> Inny operand jest konwertowany do typu float .
Warunki poprzedzające nie zostały spełnione (żaden z operandów nie jest typu zmiennoprzecinkowego). ---> Promocje całkowe są wykonywane na operandach w następujący sposób:
2. Reguły konwersji liczb całkowitych
Typy całkowite mniejsze niż int są promowane, gdy wykonywana jest na nich operacja. Jeśli wszystkie wartości typu oryginalnego mogą być reprezentowane jako int, wartość mniejszego typu jest konwertowana na int; w przeciwnym razie jest konwertowany na bez znaku int. Promocje w postaci liczb całkowitych są stosowane jako część zwykłych konwersji arytmetycznych do niektórych wyrażeń argumentów; operandy jednoargumentowych operatorów +, - i ~; i operandy operatorów zmianowych.
Całkowity ranking konwersji:
long long int
będzie wyższy niż stopieńlong int
, który będzie wyższy niż stopieńint
, który będzie wyższy niż stopieńshort int
, który będzie wyższy niż stopieńsigned char
.char
jest równa randzesigned char
iunsigned char
.Zwykłe konwersje arytmetyczne:
źródło
Cały rozdział 4 mówi o konwersjach, ale myślę, że powinieneś być zainteresowany głównie tymi:
4.5 Promocje całkowe [conv.prom]
Wartość r typu char, signed char, unsigned char, short int lub unsigned short int może zostać przekonwertowana na wartość r typu int, jeśli int może reprezentować wszystkie wartości typu źródłowego; w przeciwnym
razie źródłowa wartość r może zostać przekonwertowana na wartość r typu unsigned int.
Wartość r typu wchar_t (3.9.1) lub typ wyliczeniowy (7.2) można przekonwertować na wartość r pierwszego
z następujących typów, które mogą reprezentować wszystkie wartości typu podstawowego: int, unsigned int,
long lub unsigned długie.
Wartość r dla integralnego pola bitowego (9.6) można przekonwertować na wartość r typu int, jeśli int może reprezentować wszystkie
wartości pola bitowego; w przeciwnym razie można go przekonwertować na unsigned int, jeśli unsigned int może zastąpić
ponownie wysłał wszystkie wartości pola bitowego. Jeśli pole bitowe jest jeszcze większe, nie stosuje się do niego żadnej promocji integralnej. Jeśli pole
bitowe ma typ wyliczeniowy, jest traktowane jako każda inna wartość tego typu do celów promocyjnych.
Wartość r typu bool może zostać przekonwertowana na wartość r typu int, gdzie false staje się zerem, a true
staje się jedynką.
Te konwersje nazywane są integralnymi promocjami.
4.6 Promocja zmiennoprzecinkowa [conv.fpprom]
Wartość r typu float może zostać przekonwertowana na wartość r typu double. Wartość pozostaje niezmieniona.
Ta konwersja nazywa się promocją zmiennoprzecinkową.
Dlatego wszystkie konwersje z udziałem float - wynikiem jest float.
Tylko ten obejmujący oba int - wynik to int: int / int = int
źródło
Typ wyrażenia, gdy nie obie części są tego samego typu, zostanie przekonwertowany na największą z obu. Problem polega na tym, aby zrozumieć, który z nich jest większy od drugiego (nie ma to nic wspólnego z rozmiarem w bajtach).
W wyrażeniach, w których występuje liczba rzeczywista i liczba całkowita, liczba całkowita zostanie podniesiona do liczby rzeczywistej. Na przykład w int + float typ wyrażenia to float.
Druga różnica jest związana z możliwościami typu. Na przykład wyrażenie zawierające int i long int da wynik typu long int.
źródło
long
jest „większe” niż a,float
ale jaki jest typlong
+float
?Caveat!
Konwersje następują od lewej do prawej.
Spróbuj tego:
źródło
j + i * k
przyniesie 101.