C编译器编译i = i ++是否合法;作为系统(" rm -rf /");?

时间:2016-05-29 18:07:13

标签: c standards

未定义的行为是如何定义的?我已经阅读了各种C标准允许在第一个未定义行为之后的所有行为实际上是任意的声明。您会看到人们为i = i++;这样的语句说出四个基本的未定义级别:

    声明后
  1. " i可以是ii+1。"
  2. " i可以在声明后保留任何值。"
  3. 任何值都可能发生任何事情,或执行可能完全停止,但编译i = i++;具有system("rm -rf /");等特定副作用是不合格的。
  4. 绝对可能发生任何事情,包括system("rm -rf /");!我描述的触发器快乐文件系统销毁编译器100%符合。
  5. 我认为答案不是1,但它是哪一个(如果有的话)?如果答案取决于哪个特定的C标准,那么答案的矢量就会很好。

    编辑:linked possible duplicate并不是同一个问题(它更多地询问一条代码路径中未定义行为的可能性是否导致不确定性,无论代码路径如何),但是对this question的回答直接表明答案是4 - 即,undefined确实意味着标准对行为没有任何限制。我不确定为什么所有的downvotes ......

    第二次修改:second linked question也不重复。它只是询问为什么给定的陈述是未定义的(答案当然是序列点的微妙之处)。同样,this question's最高答案直接回答了我的问题,虽然没有权威引用(与接受的答案不同)。

1 个答案:

答案 0 :(得分:0)

正式地,“未定义的行为”定义为:

  

行为,使用不可移植或错误的程序构造或   错误的数据,本国际标准没有规定   要求

     

2注意可能的未定义行为包括忽略这种情况   完全具有不可预测的结果,在翻译过程中表现出色   或者以文件化的方式执行程序   环境(有或没有发出诊断信息),到   终止翻译或执行(发布a   诊断信息)。

这就是它的意思。这一段背后没有秘密含义,含糊不清或“圣洁真理”。

对于程序员和编译器来说,尝试推理未定义的行为是一项毫无意义的练习。对于程序员来说,当你修复错误和编写代码时,你会浪费时间担心不可移植和错误的行为。对于编译器,不可能捕获每个未定义行为的实例:这相当于停止问题。这就是为什么它首先是未定义的行为。因为这将是不合理的限制,毫无疑问,如果不是这样,编译器编写者的工作就会变得更难或不可能。

这是一个简单且技术上非类似的例子。在Brainfuck中,规范中没有任何内容说明如何处理不平衡的括号。它将简化实现,基本上不检查平衡括号(更少的代码和逻辑),代价是程序看起来正常工作,不正常工作,或seg faulting(即在空容器上进行操作)。

C是一种复杂得多的语言。如果C中没有“未定义的行为”,那么规范可能会长达1300页。