我知道写下这样的东西
++a = a++;
代码不仅难以阅读,而且违反了C/C++的序列点规则。
这些限制是从哪里来的?如何在发现它们之前就能看到这些“问题”?
我知道写下这样的东西
++a = a++;
代码不仅难以阅读,而且违反了C/C++的序列点规则。
这些限制是从哪里来的?如何在发现它们之前就能看到这些“问题”?
基本上,每个语句之间都有一个C++03序列点。更多信息请参见SO C++ FAQ。如果需要更多信息,请查阅C++标准,并记住,在C++11标准中,序列点被替换为“sequenced before”和“sequenced after”关系。
为避免问题,简单明了地在每个表达式中操作就可以了,不要试图太聪明,干预编译器的工作,留给编译器处理。你的工作是编写其他人能轻松理解的代码,即清晰的代码。多次更新和不必要的具有副作用的运算符使用与此不兼容。
提示:尽可能地使用const
。
这限制了读者必须考虑的可能状态变化。
然而,如果您编写“有趣”的代码,例如您的示例,则通常只有违反序列点要求。 语言标准可以对此类代码施加特定约束(这就是像Java这样的语言所做的),但好处并不大,并且会导致防止某些类型的优化的潜在缺陷。
如何在发现问题之前看到这些“问题”?
以最严格的级别编译您的程序,并启用所有警告设置,以便将所有警告指出为错误。大多数主流编译器确实会指出由于序列点而导致的未定义行为错误。
使用gcc时,您可以使用:
-Wsequence-point
这将指出序列点问题。请注意,如果您使用-Wall
,它将默认启用。
当然,最好的方法是尝试编写更易读的代码,避免序列点的错误。
-Wall
默认已经启用,就像我之前提到的那样。 - Alok Save++a = a++;
该语言未定义在lvalue上的前缀递增应该在rvalue上的后缀递增之前还是之后进行。在这里添加一个约束会带来显著的成本;一般的好处是什么?这个示例代码应该明显的表现出哪种行为?
为了提高性能,编译器和/或处理器可以改变程序中的操作顺序(在严格限制下)。
过度限制执行顺序会:
让我们看看如何限制不同代码示例的执行顺序:
a = b++ + ++c - --d - e--;
假设只有有限数量的寄存器可用,并且某些变量('d' 和 'e')在寄存器中,而有些则不在。 严格约束执行顺序(假设从左到右)可能需要:
而如果允许例如先处理 'd' 和 'e',稍后再递增 'b',编译器可能能够显著减少步骤并提高性能。
++a = a++
的两种情况下,a
都是一个左值,因此不应该说“在rvalue上进行后增量”,因为事实上后增量只能发生在左值上(对于内置类型)。 - M.M
-Werror -Wall -Wextra -ansi -pedantic
。 - Martin York