What is the expression -3 / 3u * 3 in C ++? You won't guess. Answer: -4. I invite you for a little investigation

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.





-4 -3, , .





, , :





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 - , . - : . , , ++. - : . ++, ++ . , , ! ++ , , ! , , ! - : . .








All Articles