为什么`x && y`不被解析为`x & (&y)`?

4

我正在实现一个C编译器,发现了一个有趣的问题。由于&的优先级高于&&,因此将其视为第一个操作数与第二个操作数的地址进行按位与运算似乎是合理的:

x && y = (x) & ( &(y) )

C规范的语法概述似乎允许这种解释。我可能漏掉或误读了一些内容?
我对语法的理解:
andExpression := equalityExpression | (andExpression '&' equalityExpression) | ... ... unaryExpression := postfixExpression | ( ('&' | '*' | '+' | '-' | '~' | '!') castExpression ) | ...

10
优先级并不涉及。&& 在语言语法起作用之前被分解为记号。现代编译器首先生成一个记号流,然后将语言语法应用于该记号流。 - Tom Karzes
2
寻找“最大匹配”规则。在每个点上,识别出可能的最长标记。 - Jonathan Leffler
@TomKarzes 谢谢,好提示。我确实没有使用分词器。但是为什么分词器可以将“&&”保持在一起而不是拆分它呢? - mafu
更多的是一个分词器不允许拆分双和号的问题——因为最大匹配规则。最大匹配规则是为什么 x = y++++z; 是虚假的 C 代码,即使它被拼写成 x = y++ + ++z; 也可以是有效的。最大匹配规则意味着它被标记为 x = y ++ ++ + z; 并且在 C 中对第二个 ++ 应用于第一个的结果是不合法的(尽管在 C++ 中似乎至少有一些时间是合法的)。 - Jonathan Leffler
除了语法原因外,您提出的解释也毫无意义。&的操作数必须具有算术类型,而&y永远不可能具有算术类型。 - R.. GitHub STOP HELPING ICE
1个回答

12

C运算表达式是通过一种被称为"maximal munch" 1)的方式进行解析的,这意味着编译器从左到右找到可以形成有效标记的最长符号块。由于x &&x &更长,因此编译器选择前者。

这就是为什么x+++1这样的代码可以编译通过,+++x则不行,但+ ++x可以。


1) C11 §6.4 词汇单元 ¶4:

如果输入流已经被解析为预处理标记直到某个字符,那么下一个预处理标记就是最长的一串字符,可以构成预处理标记。


谢谢,你能快速指出规范中描述这种行为的位置吗?应该在6.4中,但我似乎找不到它。 - mafu
2
@mafu,确实在6.4§4中(我强调):“如果输入流已经被解析成预处理令牌直到给定字符,那么下一个预处理令牌是可能构成预处理令牌的最长字符序列。” - Virgile
我在答案中添加了标准参考。 - Lundin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接