繁体   English   中英

使用三元语句作为条件的 for 循环对编译器有何影响?

[英]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 不需要一个或两个不同的循环。 发出的代码是一个实现定义的问题。

通常,通过此类微优化,请考虑:

节省您宝贵的时间来处理更大的问题。

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设置为010 ,具体取决于forward
  • i <= 10 && i >= 0 :继续,只要i010之间
  • 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM