关于C中的优先级和结合性的问题
A question about precedence and associativity in C
我有一些我不明白的问题。
既然白色 space 删除是 C
编译过程的一部分,那么 C 编译器如何区分以下内容:
案例 1:
int x = 2,y=4;
int z = x+++y;
printf("%d", z);//gives 6
案例二:
int x = 2,y=4;
int z = x+ ++y;
printf("%d", z);//gives 7
注意我在 x+
之后添加的 space,使 ++
坚持 y
而不是 x
,但这是如何发生的如果删除白色 spaces?
嗯,词法分析器并没有完全忽略空格,它的工作是获取标记并将它们传递给解析器。
在第一种情况下,词法分析器找到的标记 x
、++
、+
、y
,而在第二种情况下,x
、+
、++
、y
被词法分析器找到。
因此,与其说是运算符优先级(保持不变)的问题,不如说是词法分析器解释源代码的方式。
@PSkocik 提供了很好的参考。
为了向非计算机科学专业的毕业生说明,标记是表示语言实体的字符序列,例如变量、运算符、关键字(if、while、for、int、float...)
C 有一个贪婪的从左到右的词法分析器:
http://port70.net/~nsz/c/c11/n1570.html#6.4p4:
If the input stream has been parsed into preprocessing tokens up to a
given character, the next preprocessing token is the longest sequence
of characters that could constitute a preprocessing token.
...
所以 +++
必须被识别为 ++
+
而绝不能被识别为 +
++
.
然后,优先级和关联性决定了 ++
或 +
标记如何绑定 (http://port70.net/~nsz/c/c11/n1570.html#A.2.1)。
简单地说,后缀运算符比前缀运算符绑定更紧密,前缀运算符比二元运算符绑定更紧密。所以 x++ + y
意味着 (x++) + (y)
而不是 (x) (++(+(x))
(由于其他原因这将是荒谬的)(例如, &x->member
意味着 &(x->member)
而不是 (&x)->member
),但这里的混淆似乎只在于片段的标记化方式。
我有一些我不明白的问题。
既然白色 space 删除是 C
编译过程的一部分,那么 C 编译器如何区分以下内容:
案例 1:
int x = 2,y=4;
int z = x+++y;
printf("%d", z);//gives 6
案例二:
int x = 2,y=4;
int z = x+ ++y;
printf("%d", z);//gives 7
注意我在 x+
之后添加的 space,使 ++
坚持 y
而不是 x
,但这是如何发生的如果删除白色 spaces?
嗯,词法分析器并没有完全忽略空格,它的工作是获取标记并将它们传递给解析器。
在第一种情况下,词法分析器找到的标记 x
、++
、+
、y
,而在第二种情况下,x
、+
、++
、y
被词法分析器找到。
因此,与其说是运算符优先级(保持不变)的问题,不如说是词法分析器解释源代码的方式。
@PSkocik 提供了很好的参考。
为了向非计算机科学专业的毕业生说明,标记是表示语言实体的字符序列,例如变量、运算符、关键字(if、while、for、int、float...)
C 有一个贪婪的从左到右的词法分析器:
http://port70.net/~nsz/c/c11/n1570.html#6.4p4:
If the input stream has been parsed into preprocessing tokens up to a given character, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token.
...
所以 +++
必须被识别为 ++
+
而绝不能被识别为 +
++
.
然后,优先级和关联性决定了 ++
或 +
标记如何绑定 (http://port70.net/~nsz/c/c11/n1570.html#A.2.1)。
简单地说,后缀运算符比前缀运算符绑定更紧密,前缀运算符比二元运算符绑定更紧密。所以 x++ + y
意味着 (x++) + (y)
而不是 (x) (++(+(x))
(由于其他原因这将是荒谬的)(例如, &x->member
意味着 &(x->member)
而不是 (&x)->member
),但这里的混淆似乎只在于片段的标记化方式。