Bob*_*ski 79 c short-circuiting
是的,这是一个家庭作业问题,但我已经完成了我的研究并对这个主题进行了相当深入的思考,并且无法弄清楚这一点.问题是这段代码没有表现出短路行为,并询问原因.但它在我看来它确实表现出短路行为,所以有人可以解释为什么它没有?
在C:
int sc_and(int a, int b) {
return a ? b : 0;
}
Run Code Online (Sandbox Code Playgroud)
在我看来,如果这a
是假的,程序根本不会尝试评估b
,但我一定是错的.为什么程序b
在这种情况下甚至不需要触摸?
aru*_*nte 117
这是一个棘手的问题.b
是方法的输入参数sc_and
,因此将始终进行求值.换句话说,sc_and(a(), b())
将调用a()
和调用b()
(命令不保证),然后调用传递给sc_and
的结果.它与三元运算符本身无关,它绝对会短路.a(), b()
a?b:0
UPDATE
关于为什么我称之为"技巧问题":这是因为缺乏明确定义的背景来考虑"短路"(至少由OP再现).当给出一个函数定义时,许多人假设问题的上下文是在询问函数的主体 ; 他们通常不认为这个功能本身就是一种表达.这是问题的"诀窍"; 提醒你,在一般的编程中,尤其是像C-like这样的语言,通常有很多规则例外,你不能这样做.例如,如果问题是这样的:
请考虑以下代码.从main调用时sc_and exibit短路行为:
int sc_and(int a, int b){
return a?b:0;
}
int a(){
cout<<"called a!"<<endl;
return 0;
}
int b(){
cout<<"called b!"<<endl;
return 1;
}
int main(char* argc, char** argv){
int x = sc_and(a(), b());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
很明显,你应该用sc_and
自己的特定领域语言来考虑作为一个运算符,并评估调用是否sc_and
表现出像常规&&
那样的短路行为.我根本不认为这是一个技巧问题,因为很明显你不应该专注于三元运算符,而是应该专注于C/C++的函数调用机制(我猜,很好地写一个后续问题,写一个sc_and
短路,这将涉及使用一个#define
而不是一个功能).
你是否称之为三元运算符本身的短路(或其他类似的东西,如'条件评估')取决于你对短路的定义,你可以阅读各种意见,以便对此进行思考.它确实如此,但它与实际问题并不是非常相关,或者为什么我称它为"技巧".
hac*_*cks 42
当声明
bool x = a && b++; // a and b are of int type
Run Code Online (Sandbox Code Playgroud)
执行,b++
如果操作数被a
评估为false
(短路行为),则不会被评估.这意味着b
不会发生副作用.
现在,看看功能:
bool and_fun(int a, int b)
{
return a && b;
}
Run Code Online (Sandbox Code Playgroud)
并称之为
bool x = and_fun(a, b++);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,无论a
是true
或false
,b++
将永远是函数调用和副作用的评估过程中b
总会发生.
同样如此
int x = a ? b : 0; // Short circuit behavior
Run Code Online (Sandbox Code Playgroud)
和
int sc_and (int a, int b) // No short circuit behavior.
{
return a ? b : 0;
}
Run Code Online (Sandbox Code Playgroud)
alk*_*alk 19
正如其他人已经指出的那样,无论什么作为两个参数传递给函数,它都会在传入时进行评估.这是在tenary操作之前的方式.
另一方面,这个
#define sc_and(a, b) \
((a) ?(b) :0)
Run Code Online (Sandbox Code Playgroud)
会 "短路",因为这个宏并不意味着函数调用,并且这样就不会对函数的参数进行评估.
编辑以纠正@cmasters评论中提到的错误.
在
int sc_and(int a, int b) {
return a ? b : 0;
}
Run Code Online (Sandbox Code Playgroud)
... return
ed表达式确实显示短路评估,但函数调用没有.
试着打电话
sc_and (0, 1 / 0);
Run Code Online (Sandbox Code Playgroud)
函数调用1 / 0
虽然从未使用过,但仍会进行评估,从而导致 - 可能 - 除以零错误.
(草案)ANSI C标准的相关摘录如下:
2.1.2.3程序执行
...
在抽象机器中,所有表达式都按语义指定进行计算.实际实现不需要评估表达式的一部分,如果它可以推断出它的值未被使用并且不产生所需的副作用(包括由调用函数或访问易失性对象引起的任何副作用).
和
3.3.2.2函数调用
....
语义
...
在准备对函数的调用时,将评估参数,并为每个参数分配相应参数的值.
我的猜测是每个参数都被计算为一个表达式,但是参数列表作为一个整体不是表达式,因此非SCE行为是强制性的.
作为C标准深水表面的一个飞溅物,我很欣赏两个方面的适当信息:
1 / 0
产生不确定的行为?PS
即使你转向C++,并定义sc_and
为一个inline
函数,你也不会得到SCE.如果你将它定义为C宏,就像@alk一样,你肯定会.