☰
  • 首页
  • 规则分类
  • 项目介绍
search
•••

不可依赖未声明的求值顺序

10.2.2 ID_evaluationOrderReliance
目录 › next › previous

依赖未声明的求值顺序会导致意料之外的错误,也会降低代码的可移植性。

C 标准用“序列点(sequence point)”定义求值顺序,序列点前面的表达式先于后面的表达式求值并落实相关副作用。逻辑与、逻辑或、三元、逗号等运算符以及函数调用的左括号与序列点相关,其左子表达式先于右子表达式求值并落实副作用,赋值、算术、位运算等运算符与序列点无关,其左右子表达式的求值顺序是未声明的,函数调用表达式中各参数的求值顺序也是未声明的,详见“C 求值顺序”。

C++ 标准与 C 标准大致相同,C++17 明确了赋值、移位、数组下标等表达式的求值顺序,详见“C++ 求值顺序”。

示例:

Stack s {1, 2, 3};      // A stack, the top is 1
int pop(void);          // Pop and return the top element from the stack
int x = pop() - pop();  // Non-compliant

设 pop 函数弹出并返回栈顶元素,减号左右的两个 pop 函数哪个先执行呢?这是标准未声明的,x 的值可以是 1 - 2,也可以是 2 - 1,所以不可臆断或依赖这种未声明的求值顺序。

应改为:

int a = pop();
int b = pop();
x = a - b;      // Compliant, or ‘b - a’, depends on your needs

这样便明确了 x 的值为 1 - 2。

又如:

fun(pop(), pop());  // Non-compliant

设 fun 是函数名称或获取函数指针的表达式,标准规定 fun 会先于参数求值,但参数之间的求值顺序是未声明的。

相关

ID_confusingAssignment

依据

ISO/IEC 9899:1999 5.1.2.3(2) ISO/IEC 9899:1999 Annex C ISO/IEC 9899:2011 5.1.2.3(3) ISO/IEC 9899:2011 Annex C

参考

C++ Core Guidelines ES.43 C++ Core Guidelines ES.44 SEI CERT EXP10-C
Copyright©2024 360 Security Technology Inc., Licensed under the Apache-2.0 license.