未定义行为还是未指定行为?

12

我正在阅读这篇文章,他们使用以下示例来解释未定义的行为:

// PROGRAM 1
#include <stdio.h>
int f1() { printf ("Geeks"); return 1;}
int f2() { printf ("forGeeks"); return 1;}
int main() 
{ 
  int p = f1() + f2();  
  return 0; 
}

然而,它似乎关于子表达式的评估顺序,并且根据C标准(附录J.1),这是一种未指定的行为而不是未定义的行为:

未指定的行为:除了函数调用()、&&、||、? :和逗号操作符(6.5)指定的情况外, 子表达式的评估顺序和副作用发生的顺序。

由于我很新于阅读官方规范,我想知道我是否误解了示例或文档。我知道这可能看起来非常迂腐,但我有兴趣以正确的方式学习这些高级主题。


1
“用例来解释未定义行为”:所示代码不会调用“未定义的行为”。 - alk
8
@parallelhighway: 错了。它明确地是未指定行为,就像 OP 所认为的那样,而不是未定义行为。 - too honest for this site
1
根据@Olaf的说法,这个短语是不正确的:“程序1中未定义行为的原因是,运算符‘+’没有为其操作数定义标准的评估顺序。” - anol
1
@Olaf 你说得对,我也在文章里感到困惑。这篇文章混淆了一些术语。 - parallel highway
3
维基百科不是标准解释的好资源,只有一个权威的资源可以用于标准行为:标准本身。 - too honest for this site
显示剩余3条评论
1个回答

6
你提供的问题中给出了错误的未定义行为示例。在 f1() + f2() 中,对 f1f2 的评估将是未指定的。请注意,标准关于副作用评估顺序所述。

子表达式被评估的顺序以及副作用发生的顺序 [...]

在评估 f1f2 时产生的副作用(输出到标准输出)没有关联,并且它们不会导致任何未定义的行为。

这与下面的示例没有区别:

int a = 1;
int b = 1, c;

c = a + b;

a + b 表达式中 ab 的求值顺序未指定。


每个函数调用之前和之后都有一个序列点,因此我认为您修改后的程序也没有未定义行为。 - zwol
@zwol; 是的。但是哪个函数会先被评估?建议阅读:Is f()+g() undefined or merely unspecified? - haccks
1
仅仅是未指定的,就像原来一样。你的链接支持我的观点。 - zwol
@zwol;我想我犯了一个错误。你是正确的。 - haccks
5
在我看来,向标准输出流写入内容是一种副作用,但是在 f1f2 中存在副作用并不会导致未定义行为。 - rici
@rici; 是的,我的措辞不正确。谢谢你指出来。 - haccks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接