在 C 中循环而不进行比较 n 次
Loop without comparison n times in C
如果我有一个我知道需要执行n次的循环,有没有办法编写一个while(或for)循环而不每次进行比较?如果没有,有没有办法进行宏转换:
int i = 0;
for(i = 0; i < 5; i++) {
operation();
}
到:
operation();
operation();
operation();
operation();
operation();
附言这是我迄今为止想出的最快的循环。
int i = 5;
while(i-- >= 0) {
operation();
}
一个足够聪明的编译器会为你做到这一点。 更具体地说,优化编译器了解循环展开。 这是一个相当基本的优化,尤其是在像您的示例这样在编译时知道迭代次数的情况下。
简而言之:打开编译器优化,不要担心。
您在源代码中编写的指令数量与编译器将生成的机器指令数量没有严格关系。
大多数编译器都更聪明,在第二个示例中可以生成如下代码:
operation();
operation();
operation();
operation();
operation();
自动,因为它们检测到循环将始终迭代 5 次。
此外,如果您执行面向分析的优化,并且编译器发现循环具有很小的主体和非常高的重复计数,则即使对于具有以下代码的通用迭代次数,它也可能会展开它:
while (count >= 5) {
operation();
operation();
operation();
operation();
operation();
count -= 5;
}
while (count > 0) {
operation();
count--;
}
与朴素版本相比,这将使大count
大约五分之一的测试。
这是否值得做是只有分析才能判断的事情。
如果您确定代码至少需要执行一次,您可以做的一件事是编写
do {
operation();
} while (--count);
而不是
while (count--) {
operation();
}
对于CPU来说,count==0
的可能性有些烦人,因为在大多数编译器生成的代码中都需要额外的JMP转发:
jmp test
loop:
...operation...
test:
...do the test...
jne loop
相反,do { ... } while
版本的机器代码很简单
loop:
... opertion ...
... do the test...
jne loop
两个循环都会进行比较。
无论如何,编译器应该识别常量迭代并展开循环。
您可以使用 gcc 和优化标志 (-O) 进行检查,然后查看生成的代码。
更重要的是:除非有重要理由,否则不要优化!
编译完 C 代码后,while 和 for 循环将转换为机器语言中的比较语句,因此无法避免与 for/while 循环进行某种类型的比较。您可以制作一系列避免使用比较的 goto 和算术语句,但结果可能会效率较低。您应该研究如何使用 radare2 或 gdb 将这些循环编译为机器语言,看看如何改进它们。
使用模板,您可以使用以下内容展开循环(在编译时已知计数):
namespace detail
{
template <std::size_t ... Is>
void do_operation(std::index_sequence<Is...>)
{
std::initializer_list<std::size_t>{(static_cast<void>(operation()), Is)...};
}
}
template <std::size_t N>
void do_operation()
{
detail::do_operation(std::make_index_sequence<N>());
}
现场演示
但是编译器可能已经对正常循环进行了这种优化。
- 对于循环变体比较
- 比较两个字符串后卡在无限循环中
- string1 == string2 和你自己的 for 循环比较有什么区别?
- 循环比较(优化)
- 比较嵌套 for 循环中的两个 wchar 数组?
- 使用循环进行词典字符串比较
- 如何使用 for 循环来比较不同大小的数组
- 包含比较的循环的自动矢量化
- 在 while 循环中使用 Module32Next() 时比较wchar_t
- C++和Java的字符串循环性能比较
- 在循环C 时进行比较
- 符号和未签名整数表达式之间的比较,以进行循环误差
- For 循环仅比较数组的第一部分而不是整个数组
- r语言 - C++ 或 Rcpp:两个不带循环的向量的比较
- C++:循环浏览地图并比较键
- 如何准确测量和比较opencl速度以实现循环功能的简单速度
- 比较二维数组中的数字时的无限循环
- C++ 比较 2 个不同列表中的值以使用 2 for 循环摆脱重复的数字。无法正确检测重复项
- C++ 中 for 循环中的比较运算符
- 比较循环的不同类型的C++