简体   繁体   English

为什么变量声明可以很好地作为 for 循环的条件?

[英]Why does variable declaration work well as the condition of for loop?

What's the return value/type of a declaration like int i = 5 ?int i = 5这样的声明的返回值/类型是什么?

Why doesn't compile this code:为什么不编译这段代码:

#include <iostream>

void foo(void) {
    std::cout << "Hello";
}

int main()
{
    int i = 0;
    for(foo(); (int i = 5)==5 ; ++i)std::cout << i; 
}

while this does虽然这样做

#include <iostream>

void foo(void) {
    std::cout << "Hello";
}

int main()
{
    int i = 0;
    for(foo(); int i = 5; ++i)std::cout << i; 
}

The for loop requires condition to be either an expression or a declaration: for循环要求条件是表达式或声明:

condition - either 条件 - 要么

  • an expression which is contextually convertible to bool. 一个上下文可转换为bool的表达式。 This expression is evaluated before each iteration, and if it yields false, the loop is exited. 在每次迭代之前计算此表达式,如果它生成false,则退出循环。
  • a declaration of a single variable with a brace-or-equals initializer. 使用brace-or-equals初始化程序声明单个变量。 the initializer is evaluated before each iteration, and if the value of the declared variable converts to false, the loop is exited. 在每次迭代之前评估初始化程序,如果声明的变量的值转换为false,则退出循环。

The 1st code doesn't work because (int i = 5)==5 is not a valid expression at all. 第一个代码不起作用,因为(int i = 5)==5根本不是有效的表达式 (It's not a declaration either.) The operand of operator== is supposed to be an expression too, but int i = 5 is a declaration, not an expression. (它也不是声明。) operator==的操作数也应该是一个表达式,但是int i = 5是一个声明,而不是表达式。

The 2nd code works because int i = 5 matches the 2nd valid case for condition ; 第二个代码有效,因为int i = 5匹配条件的第二个有效情况; a declaration of a single variable with a equals initializer. 使用等于初始值设定项的单个变量的声明。 The value of i will be converted to bool for judgement; i的值将转换为bool进行判断; which is always 5 , then leads to an infinite loop. 这总是5 ,然后导致无限循环。

This code acutally complies: 此代码符合以下条件:

for (foo(); int i = 5 == 5; ++i)

It checks if 5 == 5 and set i to this boolean result (which is 1) -> infinite loop 它检查5 == 5并将i设置为此布尔结果(即1) - >无限循环

for(foo(); int i = 5; ++i)

This simply checks the value of i after being set to 5, so... when converted to bool it's always true as well -> infinite loop 这只是在设置为5之后检查i的值,所以...当转换为bool它总是也是true - >无限循环

The syntax of a for loop in C programming language is as follow: C编程语言中for循环的语法如下:

for ( init; condition; increment ) {
   statement(s);
}

The init step is executed first, and only once. init步骤首先执行,只执行一次。 You can use init to declare and initialize any loop control variables. 您可以使用init来声明和初始化任何循环控制变量。

Next, the condition is evaluated. 接下来,评估条件。 If it is true, the body of the loop is executed. 如果是,则执行循环体。 If it is false, the body of the loop does not execute and the flow of control jumps to the next statement just after the 'for' loop. 如果为false,则循环体不执行,控制流跳转到'for'循环后的下一个语句。

After the body of the 'for' loop executes, the flow of control jumps back up to the increment statement. 在执行'for'循环的主体之后,控制流会跳回到增量语句。 This statement allows you to update any loop control variables. 此语句允许您更新任何循环控制变量。

Considering your first program statement: 考虑你的第一个程序声明:

 for(foo(); (int i = 5)==5 ; ++i)std::cout << i;

The above statement will give you following error (compiled using GCC): 上面的语句会给你以下错误(使用GCC编译):

    error: expected primary-expression before ‘int’
        for(foo(); (int i = 5) == 5; ++i)std::cout << i; 

    error: expected ‘)’ before ‘int’

Primary Expression in C can be any of quite a number of things: C主表达式可以是以下任何一种:

a name (of a variable or a function)
a typename
an operator
a keyword like if or while
the list goes on and on ...

This error is due to the fact that statement (int i = 5) == 5 is not a valid expression and compiler is trying to interpret in some other way. 此错误是由于语句(int i = 5) == 5不是有效表达式而编译器试图以其他方式解释。 However, the second program works as int i = 5 declaration can be used as a valid condition for condition checking in for loop as the such declaration evaluates to value of initializer which is 5 in your second program. 但是,第二个程序作为int i = 5声明可用作for循环中condition检查的有效条件,因为此声明的计算结果为initializer程序的值,在第二个程序中为5 However, the second program will be an infinite loop and will keep printing 5 to the terminal.However, if the value of initializer was 0 , then the condition evalautes to false at it's first check and for loop body will not be executed even once. 但是,第二个程序将是一个无限循环,并将继续打印5到终端。但是,如果初始化程序的值为0 ,那么在第一次检查时条件evalautes为false,并且for循环体也不会执行一次。

Although according to a for loop's syntax the initialization statement should come first, and then the checking and then the updation, since your checking statement is an initialization in the second example, i is initialized as 5 as part of the checking and the for loop is continued. 虽然根据for循环的语法,初始化语句应首先出现,然后检查然后更新,因为你的检查语句是第二个例子中的初始化,i作为检查的一部分被初始化为5,for循环是继续。

Using the foo() call in initialization makes no difference to the for loop as the return type is void, if you put 0 in place of foo(), you will get the same output 在初始化中使用foo()调用对for循环没有任何影响,因为返回类型为void, 如果你用0代替foo(),你将获得相同的输出

Now let's consider the first example , your checking statement is an initialization, just like the second example, and it would work if you didn't have those brackets there. 现在让我们考虑第一个例子 ,你的检查语句是一个初始化,就像第二个例子一样,如果那里没有那些括号,它会起作用。 Since a declaration doesn't return any value, (int i = 5) doesn't return any value and hence cannot be compared with 5 in " == 5 ". 由于声明不返回任何值,(int i = 5)不返回任何值,因此无法与“== 5”中的5进行比较。

However, if you try "for (foo(); int i = 5 == 5; ++i)..." , the checking statement compiles the same as int i = (5 == 5) . 但是,如果你尝试“for(foo(); int i = 5 == 5; ++ i)...” ,则check语句编译与int i =(5 == 5)相同 Since 5 == 5 is true, it returns a value of 1, which is then initialized as the value of i. 由于5 == 5为真,它返回值1,然后将其初始化为i的值。 Thus the output is 11111...... 因此输出是11111 ......

TL;DR : Since a declaration doesn't return any value, (int i = 5) doesn't return any value and hence cannot be compared with 5 in " == 5 " as in the first example TL; DR: 由于声明不返回任何值,(int i = 5)不返回任何值,因此无法与“== 5”中的5进行比较,如第一个示例中所示

Problem solved. 问题解决了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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