Cel mai bun răspuns
În primul rând, o problemă: C și C ++ sunt două limbi diferite. Răspunsul de mai jos se aplică ambelor, dar uneori răspunsul diferă între limbi. Și, în ambele limbi, expresia c/c++
are comportament nedefinit.
Acesta este un mod prost pentru a obține o promoție de tip. Rețineți că exemplul din detalii este formulat mai clar:
int a, b;
long long l = a * 1ll * b;
După cum notează OP, 1ll
declară un literal long long
întreg.
prezența aici în cod promovează întreaga multiplicare la long long
prin conversii aritmetice obișnuite, în special promoții întregi.
Expresia se analizează ca ((a * 1ll) * b)
. Prima multiplicare returnează doar valoarea a
ca long long
. Cea de-a doua multiplicare se actualizează apoi la long long
.
Ați fi putut obține același efect cu o distribuție explicită:
int a, b;
long long l = (long long)a * b;
Este puțin mai tare, dar doar puțin. A doua formulare este cu siguranță mai clară, cel puțin pentru mine.
Ați putea face și ceva de genul:
long long l = a;
l *= b;
Dar asta începe să devină din nou prostesc.
În ceea ce privește motivul pentru care trebuie să promovați? Dacă aveți valori suficient de mari, multiplicarea s-ar putea revărsa. Prin promovarea la long long
, vă asigurați că nu o veți face.
Să presupunem că pe 32 de biți int
și 64- bit long long
și reprezentarea complementului 2. Cel mai mare produs pe care îl puteți obține este -2 ^ {31} \ times -2 ^ {31} = 2 ^ {62}. Aceasta este sub cea mai mare valoare pozitivă pe care o puteți reprezenta, 2 ^ {63} – 1, astfel încât să vă asigurați că nu veți revărsa.
Răspuns
a și b sunt int int * int -> int (toate în intervalul de 32 biți int ie -2147483648 int 2147483647) . „. 2147483647 * 2 = -2 și nu 4294967294 operatorul de atribuire are asociativitate de la dreapta la stânga adică în expresia: lung lung l = a * b; a * b se calculează mai întâi int * int-> int dacă a = 2147483647 și b = 2 a * b -> – 2 și nu 4294967294 acum l = -2 -2 este convertit în lung lung și stocat în l