Reguły konwersji typu Implicit w operatorach C++

Chcę być lepszy, wiedząc, kiedy powinienem rzucić. Jakie są reguły konwersji typu implicit 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 będzie zawsze oceniane jako bardziej precyzyjny Typ? Czy zasady różnią się w Javie? Proszę mnie poprawić, jeśli sformułowałem to pytanie niedokładnie.

Author: Matt Montag, 2011-04-06

9 answers

W C++ operatory (dla typów POD) zawsze działają na obiektach tego samego typu.
Tak więc, jeśli nie są one takie same, będą promowane, aby dopasować się do innych.
Typ wyniku operacji jest taki sam jak operands (po konwersji).

If either is      long          double the other is promoted to      long          double
If either is                    double the other is promoted to                    double
If either is                    float  the other is promoted to                    float
If either is long long unsigned int    the other is promoted to long long unsigned int
If either is long long          int    the other is promoted to long long          int
If either is long      unsigned int    the other is promoted to long      unsigned int
If either is long               int    the other is promoted to long               int
If either is           unsigned int    the other is promoted to           unsigned int
If either is                    int    the other is promoted to                    int
Both operands are promoted to int

Uwaga. Minimalny rozmiar operacji to int. Więc short/char są promowane do int przed wykonaniem operacji.

We wszystkich wyrażeniach int jest promowana do float przed wykonaniem operacji. Wynik operacja jest float.

int + float =>  float + float = float
int * float =>  float * float = float
float * int =>  float * float = float
int / float =>  float / float = float
float / int =>  float / float = float
int / int                     = int
int ^ float =>  <compiler error>
 179
Author: Martin York,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-27 23:13:45

Operacje arytmetyczne z udziałem float dają float.

int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int

Po Więcej Szczegółów odpowiedz. Zobacz co mówi sekcja §5/9 ze standardu C++

Wiele operatorów binarnych, które oczekują operands arytmetyki lub wyliczenia wpisz konwersje przyczyny i uzysk typy wyników w podobny sposób. Na celem jest uzyskanie wspólnego typu, który jest również typem wyniku .

Ten wzór nazywa się zwyczajnym konwersje arytmetyczne, które są zdefiniowany w następujący sposób:

- Jeśli któryś z operandów jest typu long podwójny, drugi przeliczany jest za long double.

- w przeciwnym razie, Jeśli albo operand jest podwójny, drugi jest zamienione na podwójne.

- w przeciwnym razie, jeśli jeden z operandów to float, drugi przekształca się w pływak.

- inaczej integralne promocje (4.5) wykonuje się na obu operands.54)

- wtedy, jeśli któryś z operandów jest niepodpisany long the other shall be konwertowane na unsigned long.

- w przeciwnym razie, jeśli jeden operand jest długim int i drugi niepodpisany int, następnie jeśli długi int może reprezentować wszystkie wartości niepodpisanej liczby całkowitej, niepodpisana liczba całkowita zostanie zamieniona na long int; inaczej oba operandy zostanie przeliczona na unsigned long int.

- w przeciwnym razie, jeśli któryś z operandów jest długi, drugi przeliczany jest na długa.

- w przeciwnym razie, jeśli którekolwiek z operandów jest niepodpisany, drugim jest konwertowane na niepodpisane.

[Uwaga: w przeciwnym razie jedynym pozostałym przypadkiem jest że oba operandy są int]

 28
Author: Nawaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-06 07:56:13

Ponieważ inne odpowiedzi nie mówią o regułach w C++11 oto jedna z nich. Ze standardu C++11 (projekt n3337) §5/9:

Ten wzór nazywa się zwykłymi przekształceniami arytmetycznymi , które są zdefiniowane następująco:

- Jeśli jeden z operandów jest typu wyliczania zakresu, nie są wykonywane żadne konwersje; jeśli drugi operand nie ma tego samego typu, wyrażenie jest źle utworzone.

- jeżeli jeden z operandów jest typu long double, to drugi jest konwertowany za long double.

- w przeciwnym razie, jeśli jeden z operandów jest podwójny, drugi zostanie zamieniony na podwójny.

- w przeciwnym razie, jeśli jeden z operandów jest zmiennoprzecinkowy, drugi jest konwertowany na zmiennoprzecinkowy.

- W Przeciwnym Razie całki będą wykonywane na obu operandach. Następnie do promowanych operandów stosuje się następujące zasady:

- jeśli oba operandy mają ten sam typ, nie jest potrzebna dalsza konwersja.

- inaczej, jeśli oba operandy mają podpisane typy integer lub oba mają niepodpisane typy integer, operand z typem mniejszej rangi przeliczania liczb całkowitych jest konwertowany na typ operand o większej randze.

- w przeciwnym razie, jeśli operand, który ma typ unsigned integer ma rangę większą lub równą ranga typu drugiego operandu, operand ze znakiem typu integer jest konwertowany na Typ operandu z unsigned integer type.

- W Przeciwnym Razie, jeżeli Typ operandu z signed integer może reprezentować wszystkie wartości typu operandu z unsigned integer, to operand z unsigned integer powinien być przekonwertowane na typ operandu ze znakiem typu integer.

- w przeciwnym wypadku oba operandy zostaną przekonwertowane na typ unsigned integer odpowiadający Typ operandu ze znakiem typu integer.

Zobacz tutaj aby uzyskać listę to jest często aktualizowane.

 16
Author: legends2k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-11 08:25:05

Ta odpowiedź jest w dużej mierze skierowana na komentarz autorstwa @ RafałDowgird:

"minimalny rozmiar operacji to int."- To byłoby bardzo dziwne (co z architekturami, które efektywnie obsługują char/short szef?) Czy to naprawdę w C++ spec?

Należy pamiętać, że standard C++ ma najważniejszą regułę "as-if". Patrz sekcja 1.8: wykonanie programu:

3) przepis ten nazywany jest czasem regułą "as-if", ponieważ na implementacji można dowolnie pominąć wszelkie wymagania normy dopóki wynik jest taki, jakby wymóg został spełniony, o ile jak można określić na podstawie obserwowalnego zachowania programu.

Kompilator nie może ustawić int Na rozmiar 8 bitów, nawet jeśli był najszybszy, ponieważ standard nakazuje minimum 16-bitowe int.

Dlatego, w przypadku komputera teoretycznego z superszybkimi operacjami 8-bitowymi, ukryta promocja do int arytmetyka może mieć znaczenie. Jednak w przypadku wielu operacji nie można stwierdzić, czy kompilator rzeczywiście wykonał operacje z precyzją int, a następnie przekonwertował do char, Aby zapisać je w zmiennej, lub czy operacje były wykonywane w postaci znaku.

Na przykład, rozważmy unsigned char = unsigned char + unsigned char + unsigned char, gdzie dodawanie przepełni się (Załóżmy wartość 200 dla każdego). Jeśli awansujesz do int, otrzymujesz 600, które następnie będzie domyślnie wrzucone do unsigned char, które zawiąże modulo 256, dając tym samym ostateczny wynik 88. Gdybyś nie robił takich promocji, musiałbyś zawinąć między dwoma pierwszymi dodatkami, co zmniejszyłoby problem z 200 + 200 + 200 do 144 + 200, czyli 344, co zmniejszyłoby się do 88. Innymi słowy, program nie zna różnicy, więc kompilator może zignorować polecenie wykonywania operacji pośrednich w int, jeśli operandy mają niższą rangę niż int.

Jest to prawdą w ogólnym dodawaniu, odejmowaniu i mnożeniu. To nieprawda. ogólnie dla podziału lub modułu.

 5
Author: David Stone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-20 01:24:30

Jeśli wykluczysz typy niepodpisane, to jest uporządkowany hierarchia: signed char, short, int, long, long long, float, Podwójna, długa Podwójna. Po pierwsze, wszystko przed int w powyżej zostanie przekonwertowany na int. Następnie w operacji binarnej, niższy Typ rankingowy zostanie zamieniony na wyższy, a wyniki będą typu wyższego. (Zauważ, że z hierarchia, zawsze zmiennoprzecinkowa i typ całkowy są zaangażowane, Typ całki zostanie przekształcony w floating typ punktu.)

Unsigned trochę komplikuje sprawy: zakłóca ranking, a części rankingu stają się zdefiniowane. Na to, najlepiej nie mieszać podpisane i niepodpisane w tym samym ekspresja. (Większość ekspertów C++ zdaje się unikać niepodpisanych, chyba w grę wchodzą operacje bitowe. To jest, przynajmniej, co Stroustrup poleca.)

 3
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-06 08:08:58

Moje rozwiązanie do problem dostał WA(zła odpowiedź), potem zmieniłem jedno z int na long long inti dało AC(accept) . Wcześniej próbowałem zrobić long long int += int * int, a po poprawieniu do long long int += long long int * int. Googling i camed up with,

1. Konwersje Arytmetyczne

Warunki konwersji typu:

Spełnione Warunki - - - > Konwersja

  • Każdy operand jest typu long double . --- >Inne operand jest konwersja na typ long double .

  • Warunek poprzedzający nie jest spełniony i każdy z operandów jest typu double . --- >Inny operand jest konwertowany na typ double.

  • Wcześniejsze warunki nie zostały spełnione, a każdy z nich jest typu float. --- >Inny operand jest konwertowany na typ float.

  • Wcześniejsze warunki nie zostały spełnione(żaden z operandów nie jest typu zmiennoprzecinkowego). --- >Promocje Integral są wykonywane na operandach w następujący sposób:

    • jeśli jeden z operandów jest typu unsigned long, drugi operand jest konwertowany na typ unsigned long.
    • jeśli warunek poprzedzający nie jest spełniony i jeśli jeden z operandów jest typu long, a drugi typu unsigned int , oba operandy są konwertowane na typ unsigned long .
    • jeśli dwa poprzednie warunki nie są spełnione i jeśli któryś z operandów jest typu long , t on inne operand jest konwertowany na typ long.
    • jeśli trzy poprzednie warunki nie są spełnione i jeśli jeden z operandów jest typu unsigned int, drugi operand jest konwertowany na typ unsigned int.
    • jeśli żaden z powyższych warunków nie jest spełniony, oba operandy są konwertowane na typ int.

2 . reguły przeliczania liczb całkowitych

  • Liczba Całkowita:

Typy całkowite mniejsze niż int są promowane, gdy na nich wykonywana jest operacja. Jeśli wszystkie wartości typu oryginalnego mogą być reprezentowane jako int, wartość typu smaller zostanie przekonwertowana na int; w przeciwnym razie zostanie przekonwertowana na niepodpisaną liczbę całkowitą. Promocje liczb całkowitych są stosowane jako część zwykłych konwersji arytmetycznych do pewnych wyrażeń argumentów; operandów jednoargumentowych operatorów+, - i ~ oraz operandów operatorów przesunięć.

  • Konwersja Liczb Całkowitych Ranga:

    • żadne dwa podpisane typy całkowite nie mogą mieć tej samej rangi, nawet jeśli mają tę samą reprezentację.
    • ranga podpisanego typu integer jest większa niż ranga dowolnego podpisanego typu integer z mniejszą precyzją.
    • ranga long long int jest większa niż Ranga long int, która jest większa niż ranga int, która jest większa niż Ranga short int, która jest większa niż ranga signed char.
    • ranga każdego niepodpisanego Typ integer jest równy randze odpowiadającego podpisanemu typowi integer, jeśli taki istnieje.
    • ranga dowolnego standardowego typu integer jest większa niż ranga dowolnego rozszerzonego typu integer o tej samej szerokości.
    • ranga char jest równa randze signed char i unsigned char.
    • ranga dowolnego rozszerzonego typu signed integer względem innego rozszerzonego typu signed integer z taką samą precyzją jest zdefiniowana w implementacji, ale nadal podlega innym regułom określania ranga konwersji całkowitej.
    • dla wszystkich typów całkowitych T1, T2 i T3, jeśli T1 ma większą rangę niż T2 i T2 ma większą rangę niż T3, to T1 ma większą rangę niż T3.
  • Zwykłe Przekształcenia Arytmetyczne:

    • jeśli oba operandy mają ten sam typ, nie jest potrzebna dalsza konwersja.
    • jeśli oba operandy są tego samego typu integer( signed lub unsigned), to operand z typem lesser integer conversion rank jest konwertowany na typ operand o większej randze.
    • jeśli operand z typem unsigned integer ma rangę większą lub równą randze typu drugiego operanda, to operand ze znakiem signed integer jest konwertowany na typ operandu z typem unsigned integer.
    • jeśli Typ operandu z signed integer type może reprezentować wszystkie wartości typu operandu z unsigned integer type, to operand z unsigned integer type jest konwertowany na typ operand ze znakiem typu integer.
    • w przeciwnym razie oba operandy są konwertowane na typ unsigned integer odpowiadający typowi operanda ze znakiem typu integer. Konkretne operacje mogą dodawać lub modyfikować semantykę zwykłych operacji arytmetycznych.
 2
Author: garakchy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-15 03:21:09

Cały rozdział 4 mówi o konwersjach, ale myślę, że powinieneś się nimi głównie zainteresować:

4.5 Integral promotions [conv.prom]
Wartość R typu char, signed char, unsigned char, short int lub unsigned short int można przekonwertować do wartości R typu int, jeżeli int może reprezentować wszystkie wartości typu źródłowego; other -
wise, wartość źródłowa rvalue może być przekonwertowana na wartość rvalue typu unsigned int.
Wartość R typu wchar_t (3.9.1) lub typ wyliczenia (7.2) można przekonwertować do wartości R pierwszej
następujących typów, które mogą reprezentować wszystkie wartości jego podstawowego typu: int, unsigned int,
długie lub niepodpisane długie.
Wartość R dla całkowego pola bitowego (9.6) może być przekonwertowana na wartość R typu int, jeśli int może reprezentować wszystkie
wartości pola bitowego; w przeciwnym razie może być przekonwertowane na unsigned int, jeśli unsigned int może rep -
wszystkie wartości pola bitowego. Jeśli pole bitowe jest jeszcze większe, nie ma całki dotyczy to promocji. If the
bit-field ma typ wyliczony, jest traktowany jak każda inna wartość tego typu w celach promocyjnych.
Wartość R typu bool może być przekonwertowana do wartości R typu int, z false staje się zero i true
stawanie się jednością.
Konwersje te nazywane są integral promotions.

4.6 Promocja zmiennoprzecinkowa [conv.fpprom]
Wartość R typu float może być przekonwertowana na wartość R typu double. Wartość nie zmienia się.
To konwersja nazywana jest promocją zmiennoprzecinkową.

Dlatego wszystkie konwersje z udziałem float-wynikiem jest float.

Tylko ten z udziałem obu int-wynikiem jest int : int / int = int

 1
Author: BЈовић,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-06 07:53:11

Typ wyrażenia, jeśli nie obie części są tego samego typu, zostanie przekonwertowany na największy 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 liczba rzeczywista i liczba całkowita są zaangażowane, liczba całkowita będzie promowana do liczby rzeczywistej. Na przykład w int + float typem wyrażenia jest float.

Inne różnice są związane z możliwości typu. Na przykład wyrażenie zawierające int i long int będzie wynikiem typu long int.

 1
Author: Baltasarq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-06 11:29:07

Uwaga!

Konwersje odbywają się od lewej do prawej.

Spróbuj tego:

int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0
 -1
Author: Habib,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-14 18:24:17