我看到有人使用这种方法来增加一个变量:
r = (r + 1) & 0xf;
该方法是否比仅使用更好/更快:
r++;
如果它只是重复,为什么有人会使用按位和 0xf?
我看到有人使用这种方法来增加一个变量:
r = (r + 1) & 0xf;
该方法是否比仅使用更好/更快:
r++;
如果它只是重复,为什么有人会使用按位和 0xf?
那些不一样。第一个递增 r 然后对其执行模运算,有效地做同样的事情:
r = (r + 1) % 16;
表达方式:
r = (r + 1) & 0xf;
实际上等价于这个(假设r
保证是非负的):
r = (r + 1) % 16;
因此,无法将上述任何一个陈述与r++
. 哪个“更快”或“更好”并不重要,因为它们一开始就不会做同样的事情。
正如其他人所说,您发布的两个代码片段并不相同。根据问题变成的信息更新问题,
r = (r + 1) & 0xf;
优于 ? _r = (r + 1) % 16;
尽管人们可能会想出前一种表示法更适用的情况,但我想说一般来说不,不是。模运算符使正在发生的事情变得更加清晰,我想大多数编译器都会为您执行此优化。不要为了速度而不必要地牺牲可读性。(当然,如果您想确定任何可能的速度差异,只需将两个片段编译为汇编程序,例如 with gcc -S
,然后比较输出。)
编辑: nobar下面的评论表明事情通常不像看起来那么简单。与&
,不同%
的是算术运算符,因此它与一些附加规则绑定(例如,确保正确处理否定参数)。上面的两个语句仅对非负值或 等价r
。为确保编译器可以做出这样的假设r
,最好声明它unsigned
。
这些行是不等价的。如果调用前 r 为 15,则第一个将返回零。
r++
除非您需要将预先增加的值作为右值,否则永远不应使用它来增加。如果不需要后增量功能,大多数编译器会将其优化为 ++r,但最好不要依赖它。但是您可能想要求比较++r
和(r + 1) & 0xf;
,那么我会提出,与理解和维护代码的更大难度相比,后者可能具有某个特定编译器或硬件的任何部分改进都是微不足道的。
一般来说,避免在可能不适用于其他架构的优化中过于聪明。
您提供的两个代码示例中没有等价物。
1) 是一种将值从 0 限制到 15 并在值超过 15 时回绕为零的快速方法。
2) 只是增加一个没有上限的值(除了由大小施加的固有限制之外声明 r 的类型,即如果 r 被声明为 unsigned char 等,它将包装 > 255)
1) 相当于这样做
if (r + 1 > 15 )
{
r = 0;
}
所以它在某些类型的硬件上可能更优化,因为它消除了对分支等的需要
r=(r+1) & 0xf;
当 r 是整数时,与任何类型的编译器优化进行比较,
它们应该是相同的。
++r;
r %= 0x10;
也许您应该问自己,对于维护代码的程序员来说,哪种方法清晰易懂... C 和 C++ 提供了很多语法来表达相同的内容,并且在大多数情况下编译器比程序员更聪明,因此责任是使代码易于理解。