1

我是 C 语言的新手。“优先级”是否确定了子表达式的分组。
你能解释一下子分组是如何工作的吗?

解释为什么当我确实显示错误时会出现奇怪的输出,而只是在不给出任何错误i=7; ++i+++i+++i;之间放置空格并且 Gcc 中的答案是 22;++i + ++i + ++i;这个输出是怎么来的?

我检查了书籍,其中大多数都有一些“优先”顺序,而不是一些“关联规则”,没有关于子分组的明确解释。
每当我看到这种混合表达时,你能解释一下我该怎么做吗?几乎每个 c 语言能力都会问这样的问题。

4

1 回答 1

3

这是关于 SO 的几个问题的重复,但这里有。

最大咀嚼

C 解析器将尝试抓取尽可能多的字符,以将您的程序拆分为标记。在++i+++i+++i;解析器中将字符串拆分为:

  1. ++
  2. 一世
  3. ++
  4. +
  5. 一世
  6. ++
  7. +
  8. 一世
  9. ;

然后它看到 preincrement(token 1)和 postincrement(token 3)都应用于第一个i(token 2),并报告错误。解析器不会回溯和重新解析+用于令牌 3 和++令牌 4 的字符串。如果编译器有这样做的许可,恶意程序可能会花费任意长的时间来解析。

多重副作用

C它的语言家族将序列点定义为语句执行中所有变量都具有确定值的点。序列点之间的变量发生不止一种副作用是未定义的行为。稍微简化一下你的例子。这段代码能做什么?我已将 preincrement 更改为 predecrement,以便我可以更轻松地谈论它们。

int j = ++i + --i;
  1. 增量i
  2. 将增量值用于第一个加数。
  3. 减量i
  4. 对第二个加数使用递减的值。
  5. 将这两个值相加并赋值给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上通过网络访问。

于 2013-05-05T12:20:19.070 回答