考虑以下基本示例:
我需要处理一下这段关于C89的问题吗?我尝试从这个问题中获得一些信息,但是最受欢迎的答案声称它是实现定义的,在这里绝对没有UB(伴随着Keith Thompson的评论,这看起来是矛盾的)。
在§3.16 Definitions and conventions中,规范表示:
如果在约束条件之外出现了“必须”或“不得”的要求,则行为将是未定义的。通过单词“未定义行为”或省略任何明确的行为定义,在本国际标准中显式地指示未定义行为。它们之间没有强调上的区别:它们都描述了“未定义的行为”。
和§5.1.2.2.3 Program termination:
调用
我的理解是,后面的子句并不包括缺少返回值的情况,因为
然而进一步阅读表明情况有所不同,§6.6.6.4 返回语句:
如果执行了一个没有表达式的
现在适用于
如果
术语“终止状态未定义”似乎不是UB,也不是任何特定行为,而更像是超出C标准范围的内容,更像是“让宿主环境自己担心,我们从这里开始洗手”。这个解释正确吗?
#include <stdio.h>
int main(void)
{
printf("Hi there!\n");
}
我需要处理一下这段关于C89的问题吗?我尝试从这个问题中获得一些信息,但是最受欢迎的答案声称它是实现定义的,在这里绝对没有UB(伴随着Keith Thompson的评论,这看起来是矛盾的)。
在§3.16 Definitions and conventions中,规范表示:
如果在约束条件之外出现了“必须”或“不得”的要求,则行为将是未定义的。通过单词“未定义行为”或省略任何明确的行为定义,在本国际标准中显式地指示未定义行为。它们之间没有强调上的区别:它们都描述了“未定义的行为”。
和§5.1.2.2.3 Program termination:
调用
main
函数后的返回值等同于使用main
函数返回的值作为参数调用exit
函数。如果main
函数执行了一个没有指定返回值的返回语句,则返回给宿主环境的终止状态是未定义的。我的理解是,后面的子句并不包括缺少返回值的情况,因为
return
语句从未被调用,因此前面的子句适用。然而进一步阅读表明情况有所不同,§6.6.6.4 返回语句:
如果执行了一个没有表达式的
return
语句,并且函数调用的值由调用者使用,则行为是未定义的。到达终止函数的}
相当于执行一个没有表达式的return
语句。现在适用于
5.1.2.2.3
子句。如果
main
函数执行了一个没有指定返回值的return语句,则返回给宿主环境的终止状态是未定义的。术语“终止状态未定义”似乎不是UB,也不是任何特定行为,而更像是超出C标准范围的内容,更像是“让宿主环境自己担心,我们从这里开始洗手”。这个解释正确吗?
return
,这样根据§5.1.2.2.3
所述,没有表达式的return
会导致给主机OS返回一个未定义的返回代码。你是正确的,这不是未定义行为,因为发生的事情是已知的并且总是相同的;程序将终止并将一个值作为返回代码返回给OS。 未定义的是那个值将是什么。所以,是的,我会说你的解释是正确的。 - aruisdantemain()
的尾部}
会导致程序终止。因此,这一点似乎是已定义的。然而,我倾向于说,在这种情况下是否调用exit()
是不确定的,如果调用exit()
,那么其参数的值肯定是未定义的。这些细节属于 C 标准的范围,因此该程序具有未定义行为。 - John Bollinger