¿Cuál es la expresión -3 / 3u * 3 en C ++? No lo adivinarás. Respuesta: -4. Te invito a una pequeña investigación

Todo es mucho más serio. Aquí hay un ejemplo para probar:





#include <iostream>

int main()
{
    std::cout << "-3/3u*3 = " << int(-3/3u*3) << "\n";
}
      
      



Puedes ver el resultado aquí .





O intente jugar con este ejemplo aquí o aquí .





En realidad, no pude encontrar al menos algún compilador de C ++ que produjera un resultado distinto de -4. Incluso el antiguo GCC-4.1.2 , clang-3.0.0 o Borland C 1992 . También noté que el resultado es el mismo para las constantes de tiempo de compilación y de tiempo de ejecución.





Sugiero considerar cuidadosamente el resultado de la expresión -3/3u*3



.





Si eliminamos la conversión al tipo int



en el ejemplo anterior, obtenemos 4294967292



o 0xFFFFFFF(-4)



. Resulta que el compilador realmente considera que el resultado no tiene signo y es igual 4294967292



. Hasta este punto, estaba firmemente convencido de que si se usa un tipo con signo en una expresión, el resultado se firmará. Esto es lógico.





-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