A: 最简单的回答是,如果你避开没有相当明显解释的表达式,你将也在最大程度避免未定义行为。(当然,“相当明显”对不同的人表示的意思不同。这个回答会有效,如果你同意a[i] = i++和i = i++不是“相当明显”。)
更精确一点,这里有一些更简单的规则,它们尽管比标准更保守一些,有助于确保你的代码“相当明显”和对编译器与你同伴的程序员同样可理解:
i = i + 1
因为尽管对象i出现两次并被修改,它获取i的旧值的出现(右边)被用于计算i的新值。
c = *p++
在该规则下被允许,因为两个被修改的对象(c和p)是不同的。表达式
*p++ = c
也被允许,因为p和*p(即p本身和它所指向的对象)都被修改但是几乎肯定是不同的。同样地
c = a[i++]
和
a[i++] = c
两者都被允许,因为c、i和a[i]大概都是不同的。最后这样的表达式
*p++ = *q++
和
a[i++] = b[j++]
它们中三个对象被修改(在第一个表达式中p、q和*p,第二个表达式中i、j和a[i])被允许,如果三个对象是不同的。即仅当使用了两个不同的指针p和q或两个不同的数组索引i和j。
(c = getchar()) != EOF && c != '\n'
(常见于一个读取整行输入的while循环中)是合法的,因为变量c的第二次访问出现在&&隐含的顺序点之后。(没有顺序点,这个表达式将是非法的,因为在右边与'\n'相比较时对c的访问,不能在左边“确定用于存储的值”。)
(This Chinese translation isn't confirmed by the author, and it isn't for profits.)
Translator : jhlicc@gmai1.c0m
Origin : http://www.c-faq.com/expr/confused.html