[英]What are the implications for the compiler of using a for loop with ternary statements as conditions?
您可以制作一个使用 boolean 和三元组向前或向后切换的for
循环,而不是使用具有相同printf
语句的两个不同循环。
为什么这种形式不好? 因为读不懂? 无论如何,编译器会产生两个不同的循环吗?
只是好奇这对编译结果意味着什么。
例子:
for (int i = (forward == true ? 0 : 10);
(forward == true ? i <= 10 : i >= 0);
(forward == true ? ++i : --i))
printf(" %d", i);
代替:
// Forward
for (int i = 0; i <= 10; ++i)
printf(" %d", i);
// Backward
for (int i = 10; i >= 0; --i)
printf(" %d", i);
我得到了这个有趣的建议:
for (int i = 0; i < 10; i++) {
printf(" %d", (forward ? i : 9-i));
}
使用 Godbolt 检查汇编代码后,编译器可能会进行一个(复杂的)或两个(简化的)循环。
为什么这种形式不好? 因为读不懂?
是的,这很糟糕,因为它不可读。
C 不需要一个或两个不同的循环。 发出的代码是一个实现定义的问题。
通常,通过此类微优化,请考虑:
清晰度 - for (int i = (forward == true? 0: 10);...
选择很糟糕。
维护。
节省您宝贵的时间来处理更大的问题。
C 在允许和评估表达式的方式上几乎是完全通用的,因此您几乎可以将任何您想要的 jawbreaker 表达式放入for
循环的任何(或所有三个)控制表达式(或 C 期望表达式的任何其他地方),它应该工作。
我在for
循环标头中使用了?:
,尽管正如其他答案所建议的那样,它很快就会变得不可读。
如果我必须像您询问的那样编写一个通用的向上或向下循环,我可能会这样做:
int start, end, dir;
if(forward) {
start = 0;
end = 10;
dir = +1;
} else {
start = 10;
end = 0;
dir = -1;
}
for(int i = start; i != end; i += dir) {
…
}
对于我们在此处讨论的任何循环(您最初询问的循环或任何答案中的循环),性能可能几乎相同。 像这样的细节从来都不重要,而且随着 CPU 速度越来越快,编译器的优化越来越积极,它们在今天的影响就更小了。 与往常一样,如果您真的很在意,则必须进行仔细的测量,和/或检查生成的汇编代码。 人类在此级别上对性能的预测很少准确或有用。
您现有的代码可以大大简化:
#include <stdio.h>
#include <stdbool.h>
int main(void) {
bool forward = false;
for (int i = 10*!forward; i <= 10 && i >= 0; i += 2*forward - 1)
{
printf(" %d\n", i);
}
return 0;
}
int i = 10*!forward
:将i
设置为0
或10
,具体取决于forward
i <= 10 && i >= 0
:继续,只要i
在0
和10
之间i += 2*forward - 1
:更新i
+1
或-1
,取决于forward
当forward
设置为false
时,循环输出:
10
9
8
7
6
5
4
3
2
1
0
当forward
设置为true
时,相同的循环输出:
0
1
2
3
4
5
6
7
8
9
10
同一个循环的行为可能是 go,这取决于forward:= [true | false]
forward:= [true | false]
编译器处理复杂性的能力远胜于人类。 是的,第一个例子很难阅读。
非常本着@SteveSummit 给出的答案的精神,可以在循环外明确指定边界和“方向”。
以下替代方案“知道”将至少打印一个值。
#include <stdio.h>
#include <stdbool.h>
int main( void ) {
bool forward = false;
int st = 0, inc = 1, end = 10;
if( !forward ) st = 10, inc = -1, end = 0;
do printf( " %d", st ); while( (st += inc) != (end + inc) );
return 0;
}
10 9 8 7 6 5 4 3 2 1 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.