1

来自 1987 年 IOCCC 的这条回文词条:

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

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

但是,GCC 9.3.0,即使在-std=c89模式下,也会抱怨以下实例(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)

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

我目前的想法:

在这种=情况下,我怀疑使用 (int) (tni) 作为for循环中的条件会取消它作为左值的资格,但我不确定。

在这种++情况下,我稍后可以在该代码中看到其回文性质如何迫使作者--在 (int) 和 (tni) 之间使用运算符,这不被视为问题。所以 GCC 要求在++变量之前使用运算符,而不是在它的转换之前,但是用左值抱怨来暗示这个要求。

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

提前致谢!

编辑:我很高兴地指出了一个类似的问题,它在这里回答了铸造问题 - 请参阅下面的我的评论以获取解决方案!

4

1 回答 1

2

众所周知,TCC 不是符合标准的 C 实现 - TCC 试图成为小型且快速的编译器,它试图编译正确的 C 代码,并且它通常不会产生标准要求的诊断。更广为人知的是,第一个 C 标准于 1989 年问世,而最广为人知的是 1987 年早于 1989 年。

C11 6.5.4p5

  1. 在表达式前面加上带括号的类型名称会将表达式的值转换为指定类型。这种结构称为铸件。104) 指定不转换的强制转换对表达式的类型或值没有影响。

脚注 104 指出:

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

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

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

6.5.16p2 在约束部分,因此必须诊断违规。

于 2020-10-15T10:41:11.863 回答