这是关于 SO 的几个问题的重复,但这里有。
最大咀嚼
C 解析器将尝试抓取尽可能多的字符,以将您的程序拆分为标记。在++i+++i+++i;
解析器中将字符串拆分为:
- ++
- 一世
- ++
- +
- 一世
- ++
- +
- 一世
- ;
然后它看到 preincrement(token 1)和 postincrement(token 3)都应用于第一个i
(token 2),并报告错误。解析器不会回溯和重新解析+
用于令牌 3 和++
令牌 4 的字符串。如果编译器有这样做的许可,恶意程序可能会花费任意长的时间来解析。
多重副作用
C
它的语言家族将序列点定义为语句执行中所有变量都具有确定值的点。序列点之间的变量发生不止一种副作用是未定义的行为。稍微简化一下你的例子。这段代码能做什么?我已将 preincrement 更改为 predecrement,以便我可以更轻松地谈论它们。
int j = ++i + --i;
- 增量
i
。
- 将增量值用于第一个加数。
- 减量
i
。
- 对第二个加数使用递减的值。
- 将这两个值相加并赋值给
j
。
但是,C 标准并没有固定这些效果的顺序,只是步骤 1 必须在步骤 2 之前,步骤 3 必须在步骤 4 之前,步骤 5 必须在最后。你的编译器所做的不一定是另一个编译器所做的,它不需要是一致的,即使在同一个程序中也是如此。正如行话文件中的笑话所说:
鼻恶魔, n.
Usenet 组 comp.std.c 上公认的简写,用于 C 编译器在遇到未定义构造时的任何意外行为。在 1992 年初对该组的一次讨论中,一位常客评论道:“当编译器遇到 [给定的未定义构造] 时,它让恶魔飞出你的鼻子是合法的”(暗示编译器可能会选择任意离奇的在不违反 ANSI C 标准的情况下解释代码的方法)。其他人跟进提到“鼻恶魔”,很快就确立了。原始帖子可在http://groups.google.com/groups?hl=en&selm=10195%40ksr.com上通过网络访问。