43

私は今朝ここで考えていました。もちろん、正から負へ、そして負から正へと反転する最も速い方法は何でしょうか。最も簡単な方法は次のとおりです。

int a = 10;
a = a*(-1);

また

int a = 10;
a = -a;

しかし、私は、コマンドシフトとポインターを使用してこれを行うと思いました...コマンドシフト演算子とメモリを使用して、値の符号を変更することは本当に可能でしょうか?

4

7 に答える 7

50

など、読みやすいものを使用してください。

a *= -1;

また

a = -a;

残りはオプティマイザに任せます。

于 2013-02-27T11:56:08.743 に答える
28

最適化を無効にすると、x86 の gcc は最初にこの asm にコンパイルします。

    .file   "optimum.c"
    .def    ___main;    .scl    2;  .type   32; .endef
    .text
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main               # MinGW library init function
    movl    $10, 12(%esp) ;i = 10
    negl    12(%esp)      ;i = -i
    movl    $0, %eax
    leave
    ret

最適化を無効にすると、2 番目のものは以下を生成します。

    .file   "optimum.c"
    .def    ___main;    .scl    2;  .type   32; .endef
    .text
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main
    movl    $10, 12(%esp)   ;i = 10
    negl    12(%esp)        ;i = -i
    movl    $0, %eax
    leave
    ret

同じ出力!生成されるアセンブリ コードに違いはありません。

-------------------------- 編集、彼が使用する OP 回答 VC++2012、INTEL ARCH----------- --------

を使用してコンパイルcl optimum.c /Fa optimum.asm(最適化は無効)

; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01 

    TITLE   C:\Users\Dell\Downloads\TTH\TTH\TTH\optimum.c
    .686P
    .XMM
    include listing.inc
    .model  flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC  _main
; Function compile flags: /Odtp
_TEXT   SEGMENT
_a$ = -4                        ; size = 4
_argc$ = 8                      ; size = 4
_argv$ = 12                     ; size = 4
_main   PROC
; File c:\users\dell\downloads\tth\tth\tth\optimum.c
; Line 4
    push    ebp
    mov ebp, esp
    push    ecx
; Line 5
    mov DWORD PTR _a$[ebp], 10          ; 0000000aH
; Line 6
    mov eax, DWORD PTR _a$[ebp]
    neg eax ;1 machine cycle!
    mov DWORD PTR _a$[ebp], eax
; Line 7
    xor eax, eax
; Line 8
    mov esp, ebp
    pop ebp
    ret 0
_main   ENDP
_TEXT   ENDS
END

2 番目のアプローチ ( a = a * -1) では、最適化は MSVC を無効にしました。

; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01 

    TITLE   C:\Users\Dell\Downloads\TTH\TTH\TTH\optimum.c
    .686P
    .XMM
    include listing.inc
    .model  flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC  _main
; Function compile flags: /Odtp
_TEXT   SEGMENT
_a$ = -4                        ; size = 4
_argc$ = 8                      ; size = 4
_argv$ = 12                     ; size = 4
_main   PROC
; File c:\users\dell\downloads\tth\tth\tth\optimum.c
; Line 4
    push    ebp
    mov ebp, esp
    push    ecx
; Line 5
    mov DWORD PTR _a$[ebp], 10          ; 0000000aH
; Line 6
    mov eax, DWORD PTR _a$[ebp]
    imul    eax, -1 ;1 instruction, 3 machine/cycles :|
    mov DWORD PTR _a$[ebp], eax
; Line 7
    xor eax, eax
; Line 8
    mov esp, ebp
    pop ebp
    ret 0
_main   ENDP
_TEXT   ENDS
END

したがって、MSVC でのデバッグ モード asm のパフォーマンスが気になる場合は、それに応じてソースを最適化できます。通常、最適化されたビルドでのパフォーマンスのみを気にします。

于 2013-02-27T12:03:00.447 に答える
5

また、0-n

Gccは、-n、0 --n、n * -1、および〜n+1の4つのケースすべてに対して「neg」命令を発行します。

于 2013-02-28T17:57:16.200 に答える
4

プロセッサが少なくともある程度有能で を持っていると仮定すると、sizeof(int) == sizeof(Cpu_register)「この数値を負にする」は単一の命令になります (通常は と呼ばれnegます) [まあ、値のロードと保存も必要かもしれませんが、変数を他の目的で使用している場合、ロード後に残ることができ、後でのみ保存できます...]

による乗算-1は よりも遅い可能性が高いですa = -a;が、ほとんどの有能なコンパイラはこれらの両方を同等にすることができるはずです。

したがって、コードを明確に記述するだけで、残りは自動的に処理されます。数値の否定は、ほとんどのプロセッサで難しい操作ではありません。通常とは異なるプロセッサを使用している場合は、コンパイラの出力を見て、その動作を確認してください。

于 2013-02-27T12:03:57.937 に答える
-1

あなたが試すことができます

int a = 10;
a= ~a+1;

しかし、コンパイラが最善の方法で作成するため、心配する必要はありません。

于 2013-02-27T12:02:14.497 に答える