C语言 对于编译器来说,使用带有三进制语句作为条件的for循环意味着什么?

iyzzxitl  于 2023-01-25  发布在  其他
关注(0)|答案(4)|浏览(81)

您可以创建一个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检查汇编代码后,编译器可能会生成一个(复杂)或两个(简化)循环。

jgwigjjp

jgwigjjp1#

为什么这是个糟糕的表格?因为它无法阅读?
是的,它是坏的,因为它是不可读的。
C不需要一个或两个不同的循环。发出的代码是实现定义的问题。
一般而言,此类微观优化考虑:

把你宝贵的时间省下来处理更大的问题。

r55awzrz

r55awzrz2#

C在允许和计算表达式方面几乎是完全通用的,所以你可以把你想要的任何一个jawbreaker表达式放入for循环的任何一个(或所有三个)控制表达式中(或者C期望表达式的任何其他地方),它应该可以工作。
我已经在for循环头中使用了?:,尽管正如其他答案所建议的那样,它很快就会变得不可读。
如果我必须写一个通用的,up-or-down循环,就像你问的那样,我可能会这样做:

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和越来越积极优化的编译器,它们在今天的区别甚至更小。一如既往,如果你真的关心,你必须执行仔细的测量,和/或检查生成的汇编代码。人类对这一级别性能的预测很少准确或有用。

woobm2wo

woobm2wo3#

您现有的代码可以大大简化:

#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:根据forward,将i设置为010
  • i <= 10 && i >= 0:只要i010之间,就继续
  • i += 2*forward - 1:根据forward,使用+1-1更新i

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

我相信这就是你想要的?

其中,同一循环的行为可能是任意的,具体取决于forward := [true | false]

w6mmgewl

w6mmgewl4#

编译器处理复杂性的能力远远强于人类。是的,第一个例子很难读懂。
非常符合@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

相关问题