";" 是啥意思?在“if”块内是啥意思? [复制]

Posted

技术标签:

【中文标题】";" 是啥意思?在“if”块内是啥意思? [复制]【英文标题】:What does just ";" inside an "if" block mean? [duplicate]";" 是什么意思?在“if”块内是什么意思? [复制] 【发布时间】:2017-01-11 14:04:31 【问题描述】:

为什么有人会使用它?

if(a==1); 

没有语句,只有一个分号,不会报错。 这个分号有什么作用?

【问题讨论】:

它毫无用处。这只是一句空话。 这是 C 还是 C++? 我从来没有尝试过,但是这样的空语句对调试没有用吗?喜欢添加断点? @Bathsheba 未签名行为?粉丝排队签名时会这样做吗? 它可能可能抑制关于变量a 未使用的编译器警告。但更有可能的是斯蒂芬杰伊古尔德所说的拱肩:一段代码(他正在谈论我们的遗传密码)曾经在其原始环境中发挥作用,但现在在其他部分被移除后就剩下了。跨度> 【参考方案1】:

这是一句空话。单个分号本身不执行任何操作。

在这种情况下,这意味着如果if 条件为真,则什么也不做。

如果没有else 部分,这段代码就没有多大用处。如果有,那么是否应该反转条件并且应该只包含一个非空的if 部分是一个风格问题。

在这种情况下,它是一个简单的条件,所以从风格上讲,最好将它反转,但是如果条件更复杂,那么这样写可能会更清楚。例如,这个:

if ((a==1) && (b==2) && (c==3) && (d==4)) 
    ;
 else 
    // do something useful

可能比这更清楚:

if (!((a==1) && (b==2) && (c==3) && (d==4))) 
    // do something useful

或者这个:

if ((a!=1) || (b!=2) || (c!=3) || (d!=4)) 
    // do something useful

来自 cmets 的一个更好的例子(感谢 Ben):

if (not_found) 
    ;
 else 
    // do something

对比:

if (!not_found) 
    // do something

使用哪种方法很大程度上取决于要比较的确切内容、有多少项、项的嵌套程度,甚至涉及的变量/函数的名称。

您可能会使用此功能的另一个示例是,当您有一组 if..else 语句来检查一系列值并且您希望在代码中记录特定范围内不应发生任何事情时:

if (a < 0) 
    process_negative(a);
 else if (a >=0 && a < 10) 
    process_under_10(a);
 else if (a >=10 && a < 20) 
    ;   // do nothing
 else if (a >=20 && a < 30) 
    process_20s(a);
 else if (a >= 30) 
    process_30s_and_up(a);

如果空的if 被遗漏,读者可能想知道那里是否应该发生某些事情而开发人员忘记了它。通过包含空的if,它对读者说“是的,我考虑到了这一点,在这种情况下不会发生任何事情”。

某些编码标准要求在代码中明确说明所有可能的结果。所以遵循这样一个标准的代码可能看起来像这样。

【讨论】:

我不同意might be cleaner than this。我知道这是固执己见,但至少对我来说,将代码阅读为 if none of these, do this 而不是 if this and this and this and this do nothing else do this 更容易 如果没有分号,这一切都适用。 这样写可能更清楚的具体示例:考虑名称中带有负数的标志变量,例如“not_found”。使用 "if (not_found) ; else ... " 可能比使用双重否定 "if (!not_found) ..." 更清楚 @FabioTurati:关于我们所说的,if(!(complex_condition)) /*stuff*/ if(complex_condition) else /*stuff*/ ,不,你不会。您将拥有一个执行 return (complex_condition) 的函数,此时可怕的第二个选项变得不必要了。 我只知道; 是绝对必要的一种情况。如果它们之后的下一个标记是,则需要将它放在goto 标签之后:label: 不起作用,但label: ; 会。【参考方案2】:

这叫做空语句

From 6.8.3 Expression and null statements:

空语句(仅由一个分号组成)执行 no 操作。

在这个特定的示例if(a==1); 中,它没有做任何有用的事情(除了可能更明显一点),因为它与if(a==1)if(a==1); 相同。

【讨论】:

最后,一个提到冗余的答案! 就个人而言,我更喜欢if (a == 1) ; 。你永远不会太安全。【参考方案3】:

完全没有目的。这是一句空话。如果a 不是1,则开发人员可能想做一些事情,在这种情况下,代码将类似于(即使; 仍然可以省略):

if(a==1)

  ;

else

  //useful code...

但在这种情况下,它可以很容易地写成if(a != 1)


但是请注意,如果这是 C++(标记尚不清楚),那么 a 类型的 operator== 可能会过载,并且可能会观察到一些副作用。这意味着代码很疯狂。

【讨论】:

在这种情况下,是的。但有时相反的条件(对于有用的代码)更容易写/读。作者这样做可能是为了提高可读性(无论如何在他们看来)。 但是; 字符不是必需的,是吗?您可以简单地将if 块留空并添加一个else @SomethingSomething 正确,尽管有些人认为它使它更具可读性 @GillBates 我认为正好相反;D @SomethingSomething 无论是那个还是花括号,if 之后都需要有某种声明。【参考方案4】:

就是所谓的空语句。是一种漏掉表达式的表达式语句。

有时它被用在 if-else 语句中,正如您所展示的那样,编写 if 条件比编写它的否定(或者 if 条件更清楚)更容易,但是当 if 条件被评估为 false 时应该执行代码.

例如

if ( some_condition )

   ; // do nothing

else

   // here there is some code
 

通常,null 语句仅用于说明例如函数体、类构造函数或 for 循环为空。例如

struct A

    A( int x ) : x( x )
    
        ;
    

    //...
;

或者

char * copy_string( char *dsn, const char *src )

    char *p = dsn;

    while ( ( *dsn++ = *src++ ) ) ;
                                 ^^^
    return p;

这里的while循环需要null语句。你也可以像这样重写它

    while ( ( *dsn++ = *src++ ) ) 

有时需要空语句,尤其是在使用 goto 语句的极少数情况下。例如,在 C 中,声明不是语句。如果您想将程序控制传递到某个声明之前的某个点,您可以在声明之前放置一个标签。但是在 C 中,标签只能放在语句之前。在这种情况下,您可以在声明之前放置一个带有标签的空语句。例如

Repeat:;
      ^^^
    int a[n];

    //....

    n++;
    goto Repeat;

注意标签后面的空语句。如果要删除它,C 编译器会报错。

这个技巧也用于将程序控制传递到复合语句的末尾。例如


   // some code
    goto Done;
   //...

   Done:;

虽然你不应该使用 goto 语句,但你应该知道这些情况。:)

【讨论】:

【参考方案5】:

正如许多人所说 - 它什么也没做。

为什么会在那里?这是一种可能性……

我受够了我团队中糟糕的编码人员不检查函数的返回值。

因此,由于我们在 Linux 中使用 GCC 编译器进行开发,因此我将 __attribute__((warn_unused_result)) 添加到我所有类型化函数的声明中。另请参阅 this question 以获取 MS VC 等效项。

如果用户没有检查返回值,那么编译器会产生一个警告。

当然,牛仔们玩弄了满足编译器的系统和代码if (foo() != SUCCESS) ;(尽管它不满足 :-)。

【讨论】:

OP 询问了分号的实用性,而不是 if 子句的实用性。 为什么要找我? :-) 说真的,所有其他答案都在使用if。看看 nwellnhof 目前就在这个下面……often used in long if/else chains 和其他人。弗拉德在 if-else 语句中使用的下面,等等,等等,等等我明白我们可以使用一个 semic 作为独立语句i++; /*here it comes*/ ; /* what was that for? */ j++;,但 OP 并没有这样说,所以我试图解释它在问题的上下文中(和所有其他人一样),同时还教授一个未被充分利用的语用语。【参考方案6】:

单个;null 语句,它什么都不做。它通常用于长 if/else 链,例如:

if (a == 1) 
    // Do nothing.
    ;

else if (...) 
    ...

else if (...) 
    ...

这也可以写成:

if (a != 1) 
    if (...) 
        ...
    
    else if (...) 
        ...
    

后者增加了另一个级别的缩进,但 IMO,它更清晰。但是,如果有多个没有代码的分支,null 语句有时对于避免过度缩进很有用。

请注意,一个空的复合语句(也称为)具有相同的效果:

if (a == 1) 

技术上,如果你想直接使用一个表达式语句,你只需要分号:

if (a == 1) ;
else if (...)  ... 
else if (...)  ... 

所以写; 是多余的,仅用于可疑的说明目的。

另一个来自 C 标准的示例,其中 null 语句用于提供空循环体:

char *s;
/* ... */
while (*s++ != '\0')
    ;

但在这里我也更喜欢空的复合语句。

【讨论】:

如果链中的中间项目之一将有一个空的主体,我会使用一致的if/else if 模式比反转空体案例的逻辑并将所有内容从“其他”案例转移到“真实”案例。【参考方案7】:

; 本身就是一个空语句。如果a是一个初始化的非指针类型,那么

if(a==1);

is always 在 C 中是无操作的。使用大括号为没有错字的断言增加了额外的权重。也许在它的正下方有一个else,如果a 不是1,它将执行。

【讨论】:

但不是在 C++ 中... @skyking:当然!在 C++ 中,a 可能是具有重载 == 运算符的类的实例。 @Bathsheba 在这种情况下,开发人员是疯了。【参考方案8】:

它基本上是一个 null/empty 语句,它什么都不做,本质上是预期的良性(无错误)。

C 规范草案 N1570 阐明:

    表达式是可选的:expression[opt] ; 空语句(仅由分号组成)不执行任何操作。

另一方面,Bjarne 在他的 C++ 书中引用了 #9.2 Statement Summary

分号本身就是一个语句,空语句。

注意这两个代码if(1) ;if(1) 在生成的gcc指令中有no difference。

【讨论】:

您只显示其中一个的生成代码?我想知道为什么编译器会生成一个 nop?大概是为了对齐下面的雄蕊? 不,nop 不是为了对齐。这是因为这是在没有启用优化的情况下编译的,这使得整个事情变得毫无意义。禁用优化时,编译器不关心对齐。当优化被禁用时它会发出一个 nop 以方便您在该代码行上设置断点。如果您要发布分析反汇编的答案,则需要优化代码,否则会产生误导并浪费大家的时间。 (cc @mawg) 我明白了。我懂了。这只是一个猜测。感谢您为NOP 辩护;这太有趣了。这是我可以依赖的技巧吗? (虽然我还是更喜欢asm(int 3) 是的,只显示其中一个,但是;可以很容易地注释掉,看看有没有效果。【参考方案9】:

你为什么要这样做?我在调试时一直在做类似的事情,以给我一些(我希望)不会被优化掉的东西,所以我可以在它上面设置一个断点。

虽然我很明显它是一个调试标记

if( (a==1) && (b==2) && (c==3) && (d==4) )

  int debug=1;


否则,我最终会发现到处都是奇怪的小代码,即使对我来说也完全没有意义。

但这并不能保证就是这样。

【讨论】:

【参考方案10】:

;是一个空语句 noop

它的目的是什么?

有时我们只想比较在这种情况下 a 和 1 的相等性。对于像整数这样的原始类型,这将设置条件寄存器,所以如果你有类似 if(a > 1) 或 if( a

这段代码

 int f(int a)
        if(a == 1);
        if(a > 1)return 3;
        if(a < 1)return 5;

        return 0;
 

会给

.file   "c_rcrYxj"
.text
.p2align 2,,3
.globl  f
.type   f, @function
f:
.LFB0:
    .cfi_startproc
    cmpl    $1, 4(%esp)
    jle .L6
    movl    $3, %eax
    ret
    .p2align 2,,3
.L6:
    setne   %al
    movzbl  %al, %eax
    leal    (%eax,%eax,4), %eax
    ret
    .cfi_endproc
 .LFE0:
.size   f, .-f
.ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section    .note.GNU-stack,"",@progbits

比较只进行一次cmpl $1, 4(%esp),即 if(a==1) 的确切写入位置。

【讨论】:

【参考方案11】:

您可能已经知道分号是一个空语句。关于“这个分号有什么用途”的实际问题,答案是(除非这段代码的作者想用一些奇怪的表情符号来活跃代码),它绝对没有任何目的。也就是说,;任何上下文 中的 完全等价(此处需要声明,我认为这是唯一可以使用 ; 的地方)。分号的存在将0个组成语句的复合语句变成了1个组成语句的复合语句,这是一个空语句,但这两种情况在语义上是等价的。

我将添加一个个人观点,出于可读性考虑,不会被代码读者意外忽略,; 并不比 好(如果是,那么也许;;;;;;;; 会更好),尽管两者都比单独的 ; 好得多(因此,如果根本不允许 ; 作为空语句,语言会更好,因为用 替换它总是有利的)。

【讨论】:

以上是关于";" 是啥意思?在“if”块内是啥意思? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

if any(j != " " for j in i): 是啥意思?

Excel中这行代码是啥意思,求翻译

linux上的inode编号是啥

if [ $# -ne 1 ];then 是啥意思?

点击修改的时候if判断的默认选中--condition中的值是啥意思

Excel大神谁知道这几段代码是啥意思?万分感谢,我就只有那么点财富值。