IOCCC 1987 / westley.c-GCC的左值问题

问题描述

这是1987年IOCCC的线回文录:

https://www.ioccc.org/years.html#1987_westley

...正在导致TCC 0.9.27在认编译期间没有问题,并按预期工作。

但是,即使在-std=c89模式下,GCC 9.3.0仍抱怨(int) (tni)的以下实例不是左值:

    for (; (int) (tni);)
        (int) (tni) = reviled;
                    ^
(lvalue required as left operand of assignment)
...
    for ((int) (tni)++,++reviled; reviled * *deliver; deliver++,++(int) (tni))
                                                                  ^~
(lvalue required as increment operand)

(美化代码以获得更好的上下文)

我目前的想法:

=情况下,我怀疑在for循环中使用(int)(tni)作为条件将其取消为左值,但我不确定。>

++情况下,我可以在该代码的稍后部分看到其回文性质如何迫使作者在(int)和(tni)之间使用--运算符,这不被视为问题。因此,GCC要求++运算符就在变量之前,而不是在变量之前,但是会以左值投诉提示这一要求。

这些GCC投诉是否有明确答案? TCC是否太松懈了?

谢谢!

编辑:有人向我指出了一个类似的问题,该问题在这里回答了强制转换问题-请参阅下面的评论获取解决方案!

解决方法

TCC不是众所周知的符合C的实现-TCC试图成为又小又快的编译器,尝试编译正确的C代码,并且通常不会产生诊断所需要的诊断信息标准。更广为人知的是,第一个C标准于1989年出现,而最广为人知的是1989年之前的1987年。

C11 6.5.4p5

  1. 在表达式前面加上括号类型名称可以将表达式的值转换为命名类型。这种结构称为石膏。 104)不指定任何转换的类型转换对表达式的类型或值没有影响。

脚注104指出:

  1. 强制转换不会产生左值。因此,强制转换为合格类型与强制转换为非限定版本具有相同的作用。

对于赋值运算符,6.5.16p2说:

  1. 赋值运算符的左操作数应为可修改的左值

6.5.16p2位于约束部分,因此必须诊断违反