Everything is much more serious. Here's an example to test:
#include <iostream>
int main()
{
std::cout << "-3/3u*3 = " << int(-3/3u*3) << "\n";
}
You can see the result here .
Or try playing around with this example here or here .
Actually, I could not find at least some C ++ compiler that would produce a result other than -4. Even the old GCC-4.1.2 , clang-3.0.0 or Borland C 1992 . I also noticed that the result is the same for both compile-time and run-time constants.
I propose to carefully consider the result of the expression -3/3u*3
.
If we remove the casting to the type int
in the example above, then we get 4294967292
or 0xFFFFFFF(-4)
. It turns out that the compiler actually considers the result to be unsigned and equal 4294967292
. Up to this point, I was firmly convinced that if a signed type is used in an expression, then the result will be signed. This is logical.
, , :
int main()
{
volatile unsigned B = 3;
int A = -3/B*3;
}
x86-64 clang 12.0.0 , , -3
:
mov dword ptr [rbp - 4], 3 // B = 3
mov ecx, dword ptr [rbp - 4]
mov eax, 4294967293
xor edx, edx
div ecx // !!
imul eax, eax, 3 //
mov dword ptr [rbp - 8], eax
x64 msvc v19.28 :
mov DWORD PTR B$[rsp], 3 // B = 3
mov eax, DWORD PTR B$[rsp]
mov DWORD PTR tv64[rsp], eax
xor edx, edx
mov eax, -3 ; fffffffdH
mov ecx, DWORD PTR tv64[rsp]
div ecx
imul eax, eax, 3
mov DWORD PTR A$[rsp], eax
, div
. , , imul
. . , . idiv
, .
, 4294967293
3 : 4294967293 = 1431655764 * 3 + 1
1431655764
3, 4294967292
-4
. , 4294967293
-3, , .
- .
- , (add
sub
). ( ) . add
( sub
) ( - ). . . . . (idiv
) (div
) (imul
mul
).
, , , . : msvc, gcc, clang. , . , .
Otherwise, if the unsigned operand's conversion rank is greater or equal to the conversion rank of" "the signed operand, the signed operand is converted to the unsigned operand's type.
, , .
: "the signed operand is converted to the unsigned operand's type"!! , , !! : "the unsigned operand is converted to the signed operand's type", . -3
?? .
!
int main()
{
volatile unsigned B = 3;
int C = -3*B;
}
:
mov dword ptr [rbp - 4], 3 mov eax, dword ptr [rbp - 4] imul eax, eax, 4294967293 mov dword ptr [rbp - 8], eax
. .
, - . .
! !
, , , , , ( , , ) , , , . . .
, :
? ++ , . , .
. .
int main()
{
const unsigned a[] = {3,4,5,6,7};
unsigned p = (&a[0] - &a[3])/3u*3; // -3
unsigned b = -3/3u*3; // -4
}
, , , , ( ), - , -4
-3
, Boeing 737 MAX?
, ++ , , , , .
FDIV
, 2000- FDIV
. 5 - . !!
. . .
5- ! , , ! -4
-3
-3
4294967292
! ! .
, . , . -4 , ? , ++ ? , ? , , , !
, , , , , , . , , - .
: "Signed value is intentionally converted to unsigned value. Sorry for crashing one more airplane. Have a nice flight!" , .
, . . . .
() () .
- : , 5. ?
- : , . ! ! 5, .
- : ?? _. . , , -4 ? - : ! ++ , , . -4 - , . - : . , , ++. - : . ++, ++ . , , ! ++ , , ! , , ! - : . .