-3

我知道如果while循环有这个主体:

while(a<b){
  do_some_calculations
 }

它会进行计算,然后再次检查while循环。但是如果我有一个空while循环:

while(a<b) { }

它多久检查一次条件?我知道while循环编译为cmp指令jmp(需要一到两个周期)。所以它会每1-2个周期检查一次while循环?或者不是,有些事情我不知道?详细的解释将非常有帮助。

PS问题是关于低级细节。请仔细阅读。我想知道共同的原则,而不是“它依赖于编译器等等”。

PPS 假设我们有一些有效的条件和编译器为其生成的代码。它多久会检查一次?这就是问题所在。

4

7 回答 7

4

因为标准允许在生成的程序集中有许多解决方案,所以您的问题实际上归结为“编译器做什么?” 因此只能通过示例来回答。

我使用 GCC 4.2.1(基于 Apple Inc. build 5658)(LLVM build 2336.11.00)执行了以下测试:

主.cpp:

int main() {
    while (true) { }
}

我使用以下命令行编译它:

g++ -S main.cpp

输出的精简版本 main.S 如下所示:

LBB1_1:
    jmp  LBB1_1

因此,如果没有优化,编译器会识别出没有要检查的条件,所以它只会生成一个紧密循环。

我怀疑其他编译器会做同样的事情,至少如果启用了任何优化。唯一可以确定的方法是检查:)

于 2013-03-21T11:48:37.237 回答
4

你似乎没有问正确的问题。如果问题涉及生成汇编代码的语言,您的答案将是,它取决于编译器、优化级别和某些其他因素,但最重要的是,它取决于条件。每个循环将进行一次测试。如果该测试包括访问数据库并在那里检查某些内容,那么执行循环的频率将远低于检查本地时间与某个到期时间(例如)的情况。在没有进一步了解病情的情况下, 没有可能的一般答案。当然,根据条件,编译器有时能够优化测试,但前提是代码的可见行为不依赖于它。所以从概念上讲,仍然在每次迭代时检查条件。当然,直到条件产生 false 并且循环结束。

于 2013-03-21T11:57:53.797 回答
2

您的代码将创建一个紧密的循环,但如果它是空的,它将只是一个无限循环,例如 for (;;)- 没有终止条件的循环,如果它是多核的,它将吃掉所有处理器资源或 100% / number_of_cores。在旧操作中系统这样的代码能够使整个系统“冻结”,但现在所有操作系统的调度程序都是抢占式的,因此它只会执行一个时间片(从 1 到 200 毫秒,具体取决于操作系统),并且在这个时间片内它会在每个时间段内执行而不会中断如果主体为空并且编译器由于优化而没有删除您的条件,则为 2-5 个周期。所以我认为,正如我看到的许多人认为你的问题是模糊和不正确的。

于 2013-03-21T12:22:40.660 回答
1

它将生成的代码表现得好像每次迭代都检查了条件。

如果编译器可以证明每次迭代都检查条件是不必要的,那么它可能会删除检查。但这取决于各个编译器,并且取决于您提供给它的精确代码。

于 2013-03-21T11:52:34.587 回答
1

while循环中,条件会在进入循环之前被检查,所以它会比你通过循环的次数多检查一次。

至少在抽象机器中。允许编译器进行优化。因此,在您的示例中,如果编译器可以知道aand的值b(因为例如它们之前被分配了常量),那么它可能不会生成任何代码来进行检查。如果循环明显不包含任何可以改变条件的东西,它可能会在第一次检查后不生成检查,因为结果不会改变。对编译器的唯一真正限制是可观察输出与进行比较时相同。(我认为编译器也可以假设循环在某个时候终止,并将代码移动到循环下方,等等。)

于 2013-03-21T12:28:15.803 回答
0

假设我们有一些有效的条件和编译器为它生成的代码。它多久会检查一次?这就是问题所在。

如果没有优化,则在每个循环中,如果有优化并且编译器知道您的条件不会改变,则永远不会。

于 2013-03-21T11:56:24.307 回答
0

编译器如何翻译这与 C 或 C++ 无关,只要它有效。如果编译器可以看到您的循环根本不需要运行,它可以将其删除。它可能会展开循环并完全删除除第一个检查之外的所有检查。这完全取决于编译器和代码,没有单一的答案。

如果编译器根本不进行优化,它将按照标准要求进行 - 在每次迭代开始时进行一次检查。

于 2013-03-21T11:57:31.657 回答