私は今朝ここで考えていました。もちろん、正から負へ、そして負から正へと反転する最も速い方法は何でしょうか。最も簡単な方法は次のとおりです。
int a = 10;
a = a*(-1);
また
int a = 10;
a = -a;
しかし、私は、コマンドシフトとポインターを使用してこれを行うと思いました...コマンドシフト演算子とメモリを使用して、値の符号を変更することは本当に可能でしょうか?
私は今朝ここで考えていました。もちろん、正から負へ、そして負から正へと反転する最も速い方法は何でしょうか。最も簡単な方法は次のとおりです。
int a = 10;
a = a*(-1);
また
int a = 10;
a = -a;
しかし、私は、コマンドシフトとポインターを使用してこれを行うと思いました...コマンドシフト演算子とメモリを使用して、値の符号を変更することは本当に可能でしょうか?
など、読みやすいものを使用してください。
a *= -1;
また
a = -a;
残りはオプティマイザに任せます。
最適化を無効にすると、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 のパフォーマンスが気になる場合は、それに応じてソースを最適化できます。通常、最適化されたビルドでのパフォーマンスのみを気にします。
また、0-n
Gccは、-n、0 --n、n * -1、および〜n+1の4つのケースすべてに対して「neg」命令を発行します。
プロセッサが少なくともある程度有能で を持っていると仮定すると、sizeof(int) == sizeof(Cpu_register)
「この数値を負にする」は単一の命令になります (通常は と呼ばれneg
ます) [まあ、値のロードと保存も必要かもしれませんが、変数を他の目的で使用している場合、ロード後に残ることができ、後でのみ保存できます...]
による乗算-1
は よりも遅い可能性が高いですa = -a;
が、ほとんどの有能なコンパイラはこれらの両方を同等にすることができるはずです。
したがって、コードを明確に記述するだけで、残りは自動的に処理されます。数値の否定は、ほとんどのプロセッサで難しい操作ではありません。通常とは異なるプロセッサを使用している場合は、コンパイラの出力を見て、その動作を確認してください。
あなたが試すことができます
int a = 10;
a= ~a+1;
しかし、コンパイラが最善の方法で作成するため、心配する必要はありません。