给定代码中是否存在未定义的行为?
Is undefined behavior in given code?
What is the return value of f(p,p), if the value of p is
initialized to 5 before the call? Note that the first parameter is
passed by reference, whereas the second parameter is passed by value.
int f (int &x, int c) {
c = c - 1;
if (c==0) return 1;
x = x + 1;
return f(x,c) * x;
}
Options are:
- 3024
- 6561
- 55440
- 161051
我试着解释一下:
在这段代码中,将有四个参数为(6,4)、(7,3)、(8,2) 和(9,1) 的递归调用。最后一次调用 returns 1。但是由于引用传递,前面所有函数中的 x 现在都是 9。因此,f(p,p) 返回的值将是 9 * 9 * 9 * 9 * 1 = 6561.
此题来自竞争性考试 GATE,(see Q.no.-42). The answer key is given by GATE "Marks to all" (means there is no option correct.) key set-C, Q.no.-42。某处解释为:
在 GATE 2013 中,所有标记都被给予了,因为 C/C++ 中的相同代码会产生未定义的行为。这是因为 *
不是 C/C++ 中的序列点。正确的代码必须替换
return f(x,c) * x;
和
res = f(x,c);
return res * x;
但是给定的代码工作正常。 GATE的钥匙错了吗?还是问题真的有误?
return f(x,c) * x;
这个操作的结果取决于这两个东西被求值的顺序。由于您无法预测它们的计算顺序,因此您无法预测此操作的结果。
C++03 第 5 章:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual
expressions, and the order in which side effects take place, is unspecified.
因此在 f(x,c) * x
的情况下,操作数的求值顺序是未指定的,这意味着您无法知道左操作数还是右操作数会先求值。
您的代码具有未指定的行为,这意味着它将以某种仅编译器知道的定义方式运行。程序员不知道代码会做什么,只知道它会先计算左操作数,或者先计算右操作数。出于优化目的,编译器甚至可以根据具体情况更改评估顺序。
如果求值顺序很重要,您需要重写代码。依赖于未指定行为的代码始终是一个错误,可能是一个不会立即浮出水面的非常微妙的错误。
未指定的行为不同于未定义的行为,这意味着任何事情都可能发生,包括程序失控或崩溃。
What is the return value of f(p,p), if the value of p is initialized to 5 before the call? Note that the first parameter is passed by reference, whereas the second parameter is passed by value.
int f (int &x, int c) { c = c - 1; if (c==0) return 1; x = x + 1; return f(x,c) * x; }
Options are:
- 3024
- 6561
- 55440
- 161051
我试着解释一下:
在这段代码中,将有四个参数为(6,4)、(7,3)、(8,2) 和(9,1) 的递归调用。最后一次调用 returns 1。但是由于引用传递,前面所有函数中的 x 现在都是 9。因此,f(p,p) 返回的值将是 9 * 9 * 9 * 9 * 1 = 6561.
此题来自竞争性考试 GATE,(see Q.no.-42). The answer key is given by GATE "Marks to all" (means there is no option correct.) key set-C, Q.no.-42。某处解释为:
在 GATE 2013 中,所有标记都被给予了,因为 C/C++ 中的相同代码会产生未定义的行为。这是因为 *
不是 C/C++ 中的序列点。正确的代码必须替换
return f(x,c) * x;
和
res = f(x,c);
return res * x;
但是给定的代码工作正常。 GATE的钥匙错了吗?还是问题真的有误?
return f(x,c) * x;
这个操作的结果取决于这两个东西被求值的顺序。由于您无法预测它们的计算顺序,因此您无法预测此操作的结果。
C++03 第 5 章:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.
因此在 f(x,c) * x
的情况下,操作数的求值顺序是未指定的,这意味着您无法知道左操作数还是右操作数会先求值。
您的代码具有未指定的行为,这意味着它将以某种仅编译器知道的定义方式运行。程序员不知道代码会做什么,只知道它会先计算左操作数,或者先计算右操作数。出于优化目的,编译器甚至可以根据具体情况更改评估顺序。
如果求值顺序很重要,您需要重写代码。依赖于未指定行为的代码始终是一个错误,可能是一个不会立即浮出水面的非常微妙的错误。
未指定的行为不同于未定义的行为,这意味着任何事情都可能发生,包括程序失控或崩溃。