C++ 如果(k==5)n=k;编译为if(k==5)n=5的等价形式;在visualstudioc++;?

C++ 如果(k==5)n=k;编译为if(k==5)n=5的等价形式;在visualstudioc++;?,c++,optimization,compilation,C++,Optimization,Compilation,做 编译到相当于 if (k==5) n=k; 如上面在评论中所说的,取决于k,无论是局部的、全局的、可见的、const等,而且还取决于编译优化设置。对于msvc,您可以,但不一定。在优化装配时有很多事情要考虑。举几个例子,您必须知道二进制文件占用多少字节、分支、指令执行时间和吞吐量 从一个 我们得到这个集会 int test(int k) { int n = 0; if(k == 5) { n = k; } return n; } 正

编译到相当于

if (k==5) n=k;

如上面在评论中所说的,取决于k,无论是局部的、全局的、可见的、const等,而且还取决于编译优化设置。对于msvc,您可以,但不一定。在优化装配时有很多事情要考虑。举几个例子,您必须知道二进制文件占用多少字节、分支、指令执行时间和吞吐量

从一个

我们得到这个集会

int test(int k) {
    int n = 0;

    if(k == 5) {
        n = k;
    }

    return n;
}
正如我们所看到的,这并没有将文字5移动到
n
中。事实上,它有条件地将0移动到
k
,然后将
k
移动到
n

为了理解为什么我们需要看另一个组件

int test(int):
    xor     eax, eax  ; int n = 0;  Zero out eax, the return register
    cmp     ecx, 5    ; if(k == 5); Compare edi (the register taking in the input) to 5
    cmovne  ecx, eax  ;   k = 0;    If ecx (k) was not equal to 5, zero it out
    mov     eax, ecx  ; n = k;      Set eax (the return value) to ecx (k)
    ret               ; return n;
这是相同数量的指令,但编译器可以看到一些明显的问题。第一个是条件跳转,它可能会遭受一个错误。其次,虽然这是相同数量的指令,但表示这些指令需要更多字节

MSVC生成的两个不同指令是

xor eax, eax ; Zero out eax, the return register.
cmp ecx, 5   ; Compare ecx ('k') to 5
jne Return   ; If k is not equal to five, jump to return
mov eax, 5   ; Move 5 into the return register
Return:
ret          ; Return
而跳跃式版本会产生

0f 45 c8     cmovne ecx, eax
89 c8        mov eax, ecx
正如我们所看到的,MSVC的版本需要少2个字节来表示。您描述的版本对指令缓存不好。深入了解缓存线、内存加载、指令解码和指令调度的细节需要几个小时。但归根结底是这样的:保持数据小,对单个条目使用尽可能少的缓存线,将尽可能多的其他数据条目打包到缓存线中。您可能想知道为什么将5移动到eax中需要更多的字节来表示,答案是将DWORD(4字节整数)移动到寄存器中,而要移动DWORD,您需要4个字节。然而,随着寄存器之间的移动,CPU中只有少数可访问的寄存器,因此它们可以用单个字节表示

我们在这里可以看到很多其他优化,也不能看到。例如,归零数据不是用mov完成的,而是用xor完成的。这是因为对eax进行异或操作是一项非常常见的任务,它只需要一个字节来表示助记符,另一个寄存器再加一个字节。此外,这种异或操作非常常见,几乎可以保证CPU将其解码为非常简单的移动,再次检查指令解码和调度将花费数小时

其他一些优化了的东西是推送堆栈框架,并使用堆栈进行可变存储

最后,你不应该担心这样的事情。有时微优化很重要,但通常编译器比您更清楚。他们已经阅读了,他们已经阅读了,他们直接与CPU制造商合作来改进他们的编译器


如果您有兴趣了解编译器在优化代码时考虑的一些细微差别,我强烈推荐Matt Godbolt(创建编译器资源管理器的人,让我轻松查看生成的程序集)的演讲。

取决于
k
。通常是这样。如果
k
是易失性的或原子性的,那么它就不是。试试看,看看-live-你为什么在意?两者是等价的!Basile Starynkevitch我很关心,因为它会像这样影响smth的效率:如果(k==5)n=2*k+1@如果
k
是易失性的或原子性的,则基本上不需要验证。你是对的。我只是觉得很多人过去肯定做过,这些人可能会马上给出答案。所有VAR都是局部的。@Lavroff这样的微观优化通常只有在进行大量测量和分析后才会考虑。通常有许多更有利可图的优化,如更改算法和优化内存布局等
0f 45 c8     cmovne ecx, eax
89 c8        mov eax, ecx
75 05             jne Return
b8 05 00 00 00    mov eax, 5