如果p的值为f,则f(p,p)的返回值是多少 在通话前初始化为5?请注意,第一个参数是 通过引用传递,而第二个参数按值传递。
int f (int &x, int c) { c = c - 1; if (c==0) return 1; x = x + 1; return f(x,c) * x; }
选项包括:
- 3024
- 6561
- 55440
- 161051
醇>
我试着解释一下:
在此代码中,将有四个带参数(6,4),(7,3),(8,2)和(9,1)的递归调用。最后一次调用返回1.但是由于通过引用传递,所有先前函数中的x现在是9.因此,f(p,p)返回的值将是9 * 9 * 9 * 9 * 1 = 6561。 / p>
这个问题来自竞争性考试GATE,(see Q.no.-42)。答案的关键是GATE" Marks to all" (意味着没有选项正确。)key set-C, Q.no.-42。某处解释为:
在GATE 2013中,标记被赋予所有,因为C / C ++中的相同代码会产生未定义的行为。这是因为*
不是C / C ++中的序列点。正确的代码必须替换
return f(x,c) * x;
与
res = f(x,c);
return res * x;
但是给定的代码工作正常。盖茨的关键是错的吗?或者问题确实是错误的?
答案 0 :(得分:14)
return f(x,c) * x;
此操作的结果取决于评估两件事的顺序。由于您无法预测它们的评估顺序,因此您无法预测此操作的结果。
答案 1 :(得分:9)
C ++ 03第5章:
除非另有说明,否则单个操作员的操作数和个体的子表达式的评估顺序 表达式以及副作用发生的顺序是未指定的。
因此,在f(x,c) * x
的情况下,操作数的评估顺序未指定,这意味着您无法知道左或右操作数是否会首先被评估。
您的代码具有未指定的行为,这意味着它将以某种定义的方式运行,该方式仅为编译器所知。程序员不知道代码会做什么,只是它首先评估左操作数,或者先评估右操作数。出于优化目的,甚至允许编译器根据具体情况更改评估顺序。
如果评估顺序很重要,则需要重写代码。依赖于未指定行为的代码总是一个错误,可能是一个非常微妙的错误,不会立即浮出水面。
未指定的行为与未定义的行为不同,这意味着任何事情都可能发生,包括程序变得混乱或崩溃。