C ++の式-3 / 3u * 3とは何ですか?あなたは推測しません。回答:-4。少し調査してください

すべてがはるかに深刻です。テストする例を次に示します。





#include <iostream>

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



ここで結果を見ることができます





または、ここまたはここでこの例を試してみてください





実際、-4以外の結果を生成するC ++コンパイラを少なくともいくつか見つけることができませんでした。古いGCC-4.1.2clang-3.0.0、またはBorland C1992でさえまた、コンパイル時定数と実行時定数の両方で結果が同じであることに気付きました。





式の結果を慎重に検討することをお勧めします-3/3u*3







int



上記の例のタイプへのキャストを削除すると、4294967292



またはが得られ0xFFFFFFF(-4)



ます。コンパイラは実際には結果が符号なしで等しいと見なしていることがわかり4294967292



ます。これまで、式に符号付きの型を使用すると、結果が符号付きになると確信していました。これは論理的です。





-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