For 循环不会在没有 return 语句的 int 函数中终止

For loop doesn't terminate in an int function without a return statement

在 Arduino Uno 上,for 循环在没有 return 任何东西的 int 函数中表现得非常奇怪。

void setup() {
    Serial.begin(9600);
}

void loop() {
    foo();
    Serial.println("Never reached");
}

int foo() {
    for (int i = 0; i < 9; i++) {
        Serial.println(i);
    }
}

这将输出以下内容,并继续无限循环通过 ASCII...

0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D

此外,将 for 条件设置为 i < 12 使其永远按数字计数,ASCII 输出的 none。

这一切都可以通过向 foo() 添加 return 0; 来解决,但我很好奇为什么会这样。有什么想法吗?

C++ 语言有一个概念undefined behavior。可以写出不构成程序的代码。

Once 未定义行为的示例不是 return 从声明为 int foo() 的函数中获取值。从优化编译器的角度来看,函数永远不会 returns,因为如果没有 returning 一个 int 值,就不可能从 int foo() 到 return,所以它优化循环结束条件。

检查您的编译器警告 - 应该有一个关于可能缺少 return.

的警告

如果您不打算 return 来自 foo() 的任何内容,则应声明为 void foo()

有错误的代码会以奇怪且不可预测的方式运行。如您所见,修复错误后,问题就消失了。

在这种情况下,编译器可能注意到缺少 return 语句并得出结论,因此循环绝不能终止。由于无法从一个函数中 return 某些东西失败是不允许的 return 某些东西,因此编译器推断出该代码是无法访问的。因此它删除了循环终止测试作为优化。

允许编译器假设您的代码是正确的(除非需要诊断)并使用它来优化您的代码。这对没有错误的代码有巨大的好处。

要求编译器假定您的代码中可能存在错误是非常不切实际的。这也是毫无意义的,毕竟,当代码必须 return 一个值未能达到 return 值时,编译器在 运行 时间无法做任何明智的事情。

您可能认为完美的编译器会在编译时产生错误——但怎么可能呢?它怎么知道编译这段代码时 Serial.println(i); 总是 return?

强烈建议在 C++ 中的任何非 void 函数中添加 return 语句。您只需要将函数类型更改为 void 或向其添加 return 语句即可。

#1:

void foo() {
   Serial.println("foo");
}

#2:

int foo() {
   Serial.println(""foo);
   return 0;
}