我的问题是我在本主题中提到的那行,在生产代码中的很多地方都可以看到。
总体代码如下:
if (0) {
// Empty braces
} else if (some_fn_call()) {
// actual code
} else if (some_other_fn_call()) {
// another actual code
...
} else {
// default case
}
其他分支与我的问题无关。我想知道将if (0)
放在这里的含义是什么。花括号是空的,所以我不认为它应该注释一些代码块。它会迫使编译器进行一些优化还是其意图不同?
我曾尝试在SO和互联网上搜索这种明显的情况,但没有成功。关于JavaScript,也有类似的问题,但没有关于C的问题。还有另一个问题,What happens when a zero is assigned in an `if` condition?,但它讨论了变量的零赋值,而不是'if(0)'用法本身。
答案 0 :(得分:104)
如果有#if
条语句,这会很有用
if (0)
{
// Empty block
}
#if TEST1_ENABLED
else if (test1())
{
action1();
}
#endif
#if TEST2_ENABLED
else if (test2())
{
action2();
}
#endif
等
在这种情况下,可以#if
进行任何(和所有)测试,并且代码可以正确编译。几乎所有的编译器都将删除if (0) {}
部分。
一个简单的自动生成器可以生成这样的代码,因为它更容易编码-不必单独考虑第一个启用的块。
答案 1 :(得分:89)
我有时将其用于对称性,因此我可以与其他编辑者自由移动else if{
,而不必介意第一个if
。
语义上
if (0) {
// Empty braces
} else
part不会执行任何操作,您可以依靠优化程序将其删除。
答案 2 :(得分:44)
我已经看到在生成的代码中使用了类似的模式。例如,在SQL中,我已经看到库发出以下where
子句。
where 1 = 1
这大概使添加其他条件变得更加容易,因为所有其他条件都可以用and
开头,而不是进行其他检查以查看它是否是第一个条件。
答案 3 :(得分:42)
按照书面规定,if (0) {}
子句编译为空。
我怀疑此阶梯顶部的子句的功能是提供一个方便的位置,通过将0
更改为{{,以暂时禁用所有其他功能(出于调试或比较目的)) 1}}或1
。
答案 4 :(得分:15)
我不确定是否有任何优化,但是我有两分钱:
之所以发生这种情况,是因为进行了一些代码修改,其中删除了一个主要条件(例如,在初始if
块中的函数调用),但是开发人员/维护人员
if-else
块因此,他们没有删除关联的if
块,而是只是将条件更改为if(0)
并继续前进。
答案 5 :(得分:15)
尚未提及的一种可能性:if (0) {
行可能为断点提供了方便的位置。
调试通常是在未优化的代码上进行的,因此将始终存在错误测试,并能够在其上设置断点。当编译用于生产时,代码行将被优化。看似无用的产品线为开发和测试版本提供了功能,而不会影响发行版本。
上面还有其他好的建议;真正了解目的的唯一方法是追踪作者并提出要求。您的源代码控制系统可能会帮助您。 (寻找blame
类型的功能。)
答案 6 :(得分:14)
代码腐烂。
在某些时候,“如果”做了一些有用的事情,情况就发生了变化,也许正在评估的变量被删除了。
正在修理/更改系统的人做了尽可能少的事情来影响系统的逻辑,因此他只是确保代码可以重新编译。所以他留下了一个“ if(0)”,因为这很容易,而且他也不完全确定那是他想要做的。他使系统正常工作,并且没有回去完全修复它。
然后下一个开发人员出现并认为这是故意完成的,并且只注释掉了该部分代码(因为无论如何都没有对其进行评估),然后下次修改该代码时,这些注释被删除。
答案 7 :(得分:9)
我已经看到了使用模板语言生成的预扩展JavaScript中无法访问的代码块。
例如,您正在读取的代码可能是从服务器粘贴的,该服务器预先评估了当时仅依赖于服务器端可用变量的第一个条件。
Session
曾经被预编译过的
if ( ${requestIsNotHttps} ){ ... }else if( ...
希望这可以帮助您恢复亲回收编码器时代潜在的低键盘活动,对此我表现出热情!
答案 8 :(得分:8)
该构造也可以在C语言中用于实现类型安全的泛型编程,这取决于以下事实:编译器仍会检查无法访问的代码:
// this is a generic unsafe function, that will call fun(arg) at a later time
void defer(void *fun, void *arg);
// this is a macro that makes it safer, by checking the argument
// matches the function signature
#define DEFER(f, arg) \
if(0) f(arg); \ // never actually called, but compile-time checked
else defer(f, (void *)arg); // do the unsafe call after safety check
void myfunction(int *p);
DEFER(myfunction, 42); // compile error
int *b;
DEFER(myfunction, b); // compiles OK
答案 9 :(得分:6)
我认为这只是错误的代码。在Compiler Explorer中写一个简单的例子,我们看到在gcc和clang中,即使完全禁用了优化,也不会为if (0)
块生成代码:
尝试删除if (0)
不会更改生成的代码,因此我得出结论,这不是一种优化。
顶部if
块中可能有某些内容后来被删除了。简而言之,似乎删除它会导致生成完全相同的代码,所以请随意这样做。
答案 10 :(得分:6)
如前所述,零的计算结果为false,分支可能会被编译器优化。
我之前在代码中也看到了这一点,在代码中添加了一个新功能,并且需要一个kill-switch(如果该功能出了问题,您可以将其关闭),然后再过一段时间,当kill-switch出现时被删除,程序员也没有删除分支,例如
if (feature_a_active()) {
use_feature_a();
} else if (some_fn()) {
...
成为
if (0) {
// empty
} else if (some_fn()) {
...
答案 11 :(得分:1)
仅在将块1放入时,这有助于调试该块。这将禁用所有if else块功能。而且我们还可以扩展if else块。
答案 12 :(得分:1)
@PSkocik的回答很好,但是我加了两美分。不确定我应该作为评论还是作为答案;选择后者,是因为恕我直言值得其他人看到,而评论则经常不可见。
我不仅偶尔使用
if(0) {
//deliberately left empty
} else if( cond1 ) {
//deliberately left empty
} else if( cond2 ) {
//deliberately left empty
...
} else {
// no conditions matched
}
但我偶尔也会这样做
if( 1
&& cond1
&& cond2
...
&& condN
) {
或
if( 0
|| cond1
|| cond2
...
|| condN
) {
用于复杂条件。出于相同的原因-易于编辑,#ifdef等
为此,我将在Perl中进行
@array = (
elem1,
elem2,
...
elem1,
) {
我将if(0)
代码与lisp进行比较
(cond (test1 action1)
(test2 action2)
...
(testn actionn))
您猜对了,我可能缩进为
(cond
(test1 action1)
(test2 action2)
...
(testn actionn)
)
我有时试图想像一下这种可能更具人类可读性的语法。
也许
IF
:: cond1 THEN code1
:: cond2 THEN code2
...
:: condN THEN codeN
FI
受到Dikstra的[https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if][Guarded命令语言]的启发。
但是这种语法意味着条件是并行评估的,而if...else-if
意味着条件的顺序评估和优先评估。
在编写会生成其他程序的程序时,我开始做这种事情,这特别方便。
尽管如此,当使用英特尔旧的iHDL编写RTL时,我已经编写了类似的代码
IF 0 THEN /*nothing*/
**FORC i FROM 1 TO 10 DOC**
ELSE IF signal%i% THEN
// stuff to do if signal%i% is active
**ENDC**
ELSE
// nothing matched
ENDIF
其中FORC..DOC..ENDC
是宏预处理器循环结构,它扩展为
IF 0 THEN /*nothing*/
ELSE IF signal1 THEN
// stuff to do if signal1 is active
ELSE IF signal2 THEN
// stuff to do if signal2 is active
...
ELSE IF signal100 THEN
// stuff to do if signal100 is active
ELSE
// nothing matched
ENDIF
这是单次分配的非强制性代码,因此,如果您需要执行诸如查找第一个设置位之类的操作,则不允许设置状态变量。
IF 0 THEN /*nothing*/
ELSE IF signal1 THEN
found := 1
ELSE IF signal2 THEN
found := 2
...
ELSE IF signal100 THEN
found := 100
ELSE
// nothing matched
ENDIF
想一想,这可能是我第一次遇到这样的结构。
顺便说一句,有些人对if(0)风格有异议-else-if条件是顺序依赖的,不能随意重新排序-不适用于RTL中的AND和OR和XOR逻辑-但确实适用短路&&和||。
答案 13 :(得分:1)
Actually according to my opinion, if we put any variable for checking inside
e.g:-
public static void main(string args[])
{
var status;
var empList=_unitofWork.EmpRepository.Get(con=>con.isRetired==true);
//some code logic
if(empList.count>0)
{
status=true;
}
if(status)
{
//do something
}
else
{
//do something else
}
}
if then its dynamically get the value in run time and invoke the logic inside it, else its simply extra line of code i guess.
Anybody have any depth knowledge why this thing is used....or agree with me.
kindly respond.
答案 14 :(得分:-1)
例如,我已经看到它用于处理错误
if(0){
lable1:
//do something
}
if(0){
lable2:
//do something
}
.
.
and so on.
if(condition_fails)
goto lable1;
这在使用goto来管理错误时非常有用,仅在发生错误时才执行语句。我在非常古老的C代码中看到了这一点(函数参数写在'()'之外),不要以为现在有人遵循了。
答案 15 :(得分:-2)
我已经看过几次了,我认为最可能的原因是它正在评估旧版本/不同版本的代码/分支中的某些内容,或者可能是为了进行调试,然后将其更改为if(0)
删除其中所有内容的方法有些懒惰。