什么只是";"在"如果"块意味着什么

时间:2017-01-11 14:04:31

标签: c

为什么有人会用这个?

if(a==1){;} 

没有声明,只有一个分号,并且它不会抛出错误。 这个分号的用途是什么?

11 个答案:

答案 0 :(得分:53)

这是一个空洞的陈述。单个分号本身不执行任何操作。

在这种情况下,这意味着如果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
}

评论中的一个更好的例子(感谢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,它向读者说“是的,我解释了这一点,在这种情况下不会发生任何事情”。

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

答案 1 :(得分:46)

它被称为 null语句

From 6.8.3 Expression and null statements

  

null语句(仅由分号组成)执行no   操作

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

答案 2 :(得分:18)

完全没有目的。这是一个空洞的陈述。如果a不是1,那么开发人员可能会做一些事情,在这种情况下,代码会是这样的(即使;仍然可以省略):

if(a==1)
{
  ;
}
else
{
  //useful code...
}

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

但请注意,如果这是C ++(标签尚不清楚),那么类型operator==的{​​{1}}可能会过载,并且可能会观察到一些副作用。这意味着代码仍然是疯了。

答案 3 :(得分:13)

它被称为null语句。这是表达式遗漏的表达式。

有时它会在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++ ) ) {}

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

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

    //....

    n++;
    goto Repeat;

注意标签后面的空语句。如果要删除它,那么C编译器将发出错误。

此技巧还用于将程序控制传递给复合语句的末尾。例如

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

   Done:;
}

虽然您不应该使用goto语句,但您应该了解这些情况。:)

答案 4 :(得分:8)

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

为什么会这样?这是一种可能性...

我厌倦了我的团队中的不良编码员,而不是检查函数的返回值。

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

如果用户未检查返回值,则编译器会生成警告。

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

答案 5 :(得分:7)

单个; 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')
    ;

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

答案 6 :(得分:4)

它基本上是一个 null / empty 语句,它 ,并且本质上是预期的良性(无错误)。

C Spec草案N1570 澄清:

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

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

  

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

请注意,这两个代码if(1) {;}if(1) {}在生成的gcc说明中都有no difference

答案 7 :(得分:4)

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

if(a==1){;}

始终是C中的无操作。使用大括号会增加额外的权重,即断言没有拼写错误。也许正下方有一个else,如果a不是1,就会执行。

答案 8 :(得分:1)

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

通常虽然我明确表示它是一个调试标记

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

  int debug=1;

}

否则我最终会发现奇怪的一点点代码卡在任何地方,即使对我来说也毫无意义。

但这不能保证这是什么。

答案 9 :(得分:0)

是一个空的声明noop

它的目的是什么?

有时候我们只想比较像这样的情况a和1的等价。对于像整数这样的原始类型,这将设置条件寄存器,所以如果你之后有if if(a&gt; 1)或者if (a&lt; 1),并且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)。

答案 10 :(得分:0)

您可能已经知道分号是一个空语句。关于实际问题“这个分号的用途是什么”,答案是(除非该代码的作者希望用一些奇怪的表情符号使代码活跃起来),它绝对是没有任何目的。也就是说,{;}完全等同于任何上下文中的{} (其中需要一个语句,我认为这是唯一可以使用{;}的地方)。分号的存在将带有0个组成语句的复合语句更改为带有1个组成语句的复合语句,这是一个空语句,但就语义而言,这两个案例是等效的。

我会添加一个个人观点,为了让读者不会被代码的读者意外忽略,{;}并不比{}更好(如果是,那么可能{{1}虽然两者都比单独的{;;;;;;;;}要好得多(因此,在没有允许;作为空语句的情况下,语言会更好,因为将其替换为;总是有利的。)