以下两个代码序列产生相同的结果:

uint mod = val % 4;

uint mod1 = val & 0x3;

我可以使用两者来计算相同的结果。我知道在硬件中,&运算符比%运算符实现起来简单得多。因此,我希望它比%运算符具有更好的性能。

我是否可以始终假设&具有更好或相等的性能?
编译器会自动优化吗?

最佳答案

您不能对这些操作中的任何一个假设任何东西,编译可以将它们优化为相同的指令。

而且,的确,clanggcc都会将它们转换为一条and指令。

不幸的是,由于自ISO C99以来%具有指定的负值返回值的性质,因此signed整数需要一些额外的工作。与ISO C90相对,后者定义了负模。

两种操作在signedunsigned值上的结果汇编:

带有有符号整数的 modulo:

mov     eax, DWORD PTR [esp+4]       ; grab `val`
cdq                                  ; convert 32-bit EAX to 64-bit
                                     ; and fill EDX with the sign bit
shr     edx, 30                      ; shift EDX by 30 positions to the right
                                     ; leaving only the two left-most bits
add     eax, edx                     ; add EDX to EAX
and     eax, 3                       ; do the AND
sub     eax, edx                     ; subtract EDX from EAX
mov     DWORD PTR [esp+8], eax       ; move result on stack

这是一个巧妙的技巧,可以为负值正确定义行为。负值表示((val + 3) & 3) - 3,正值表示val & 3

带有签名/未签名的和带有未签名的and:
mov     eax, DWORD PTR [esp+4]
and     eax, 3
mov     DWORD PTR [esp+12], eax

关于c - 是否存在 '&'的性能低于 '%'的情况?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37180903/

10-11 20:36