【发布时间】:2015-03-28 00:24:48
【问题描述】:
考虑以下基本示例:
#include <stdio.h>
int main(void)
{
printf("Hi there!\n");
}
它会调用 C89 中的未定义行为吗?我试图从this question 中获得一些意义,但大多数赞成的答案声称它是由实现定义的,而且这里绝对没有 UB(与 Keith Thompson 的 cmets,这看起来很矛盾)。
规范在 §3.16 定义和约定中说:
如果“应”或“不应”要求出现在 违反了约束。行为未定义。未定义的行为 在本国际标准中另有说明 “未定义的行为”或省略任何明确的定义 行为。这三者在侧重点上没有区别:它们 都描述了“未定义的行为”。
和§5.1.2.2.3 程序终止:
对
main函数的初始调用的返回等效于 使用main函数返回的值调用exit函数 作为它的论据。如果main函数执行返回指定 无值,返回宿主环境的终止状态为 未定义。
我的理解是后一个子条款不包括缺少返回的情况,因为return 语句从未被调用过,因此前一个子条款适用。
但进一步阅读表明有所不同,§6.6.6.4 return 声明:
如果执行了没有表达式的
return语句,并且值 函数调用被调用者使用,行为是未定义的。 到达终止函数的}相当于执行一个return不带表达式的语句。
好的,现在5.1.2.2.3 子条款适用:
如果
main函数执行返回指定 没有价值。返回宿主环境的终止状态为 未定义。
术语“终止状态未定义”似乎不是UB,也不是任何特定行为,而是更像是超出了C标准的范围,更像是:“让宿主环境不用担心,我们从这里洗手”。理解正确吗?
【问题讨论】:
-
如果您还没有看到,这里有一些有趣的答案:stackoverflow.com/q/204476/3933332
-
My go-to C89 draft 与您给出的报价完全不符。章节号完全不同,对应的文字也不同。当然,这是一个草案,而不是最终标准。然而,如果我们不同意标准,我们就不可能就答案达成一致。
-
我会读到这相当于在没有表达式的情况下调用
return,然后根据§5.1.2.2.3声明没有表达式的return会导致未定义的返回码到主机操作系统.你是对的,这不是未定义的行为,因为发生的事情是已知的并且总是相同的;程序将终止,并将一个值作为返回码返回给操作系统。 is undefined 就是那个值。所以是的,我会说你的解释是正确的。 -
It is allowed in C99。虽然这不能回答您关于 C89 的问题,但我认为从编译器编写者的角度来看,在 C89 中触发 UB 但在 C99 中具有明确定义的行为会很疯狂。这甚至可能被认为是 C89 中的一个缺陷。
-
根据您提供的标准摘录,我说在“返回到主机环境的终止状态未定义”中暗示到达
main()的尾随}会导致程序终止。因此,这似乎已定义。我倾向于说它是未定义的,但是,在这种情况下是否调用exit(),如果是,那么它的参数的值肯定是未定义的。这些细节都在 C 标准的范围内,所以程序确实有未定义的行为。
标签: c language-lawyer c89