Najlepsza odpowiedź
Po pierwsze, uwaga: C i C ++ to dwa różne języki. Poniższa odpowiedź dotyczy obu, ale czasami odpowiedź różni się w zależności od języka. W obu językach wyrażenie c/c++
ma niezdefiniowane zachowanie.
To jest głupi sposób na promocję typu. Zwróć uwagę, że przykład w szczegółach jest sformułowany jaśniej:
int a, b;
long long l = a * 1ll * b;
Jak zauważa OP, 1ll
deklaruje long long
literał liczby całkowitej.
Jego obecność w kodzie promuje całe mnożenie do long long
poprzez zwykłe konwersje arytmetyczne, w szczególności promocje w postaci liczb całkowitych.
Wyrażenie jest analizowane jako ((a * 1ll) * b)
. Pierwsze mnożenie po prostu zwraca wartość a
jako long long
. Drugie mnożenie zostanie następnie zaktualizowane do long long
.
Możesz uzyskać ten sam efekt z wyraźnym rzutowaniem:
int a, b;
long long l = (long long)a * b;
To trochę więcej pisania, ale tylko trochę. Drugie sformułowanie jest z pewnością jaśniejsze, przynajmniej dla mnie.
Możesz też zrobić coś takiego:
long long l = a;
l *= b;
Ale to znowu zaczyna być głupie.
Dlaczego musisz promować? Jeśli masz wystarczająco duże wartości, mnożenie może się przepełnić. Promując do long long
, gwarantujesz, że tak się nie stanie.
Załóżmy, że 32-bitowe int
i 64- bit long long
i uzupełnienie do 2. Największy produkt, jaki możesz uzyskać, to -2 ^ {31} \ times -2 ^ {31} = 2 ^ {62}. To poniżej największej dodatniej wartości, jaką możesz przedstawić, 2 ^ {63} – 1, więc masz gwarancję, że nie przepełnisz.
Odpowiedź
a i b to int int * int -> int (wszystko w zakresie 32-bitowym int tj. -2147483648 int 2147483647) . „. 2147483647 * 2 = -2 a nie 4294967294 operator przypisania ma asocjację od prawej do lewej , tj. W wyrażeniu: long long l = a * b; a * b jest obliczane jako pierwsze int * int-> int, jeśli a = 2147483647 i b = 2 a * b -> – 2 a nie 4294967294 teraz l = -2 -2 jest konwertowane na long long i przechowywane w l