“if”块中的“;”是什么意思?

为什么有人会用这个?

if(a==1){;} 

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

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

在这种情况下,这意味着if条件成立,则什么都不做。

没有else部分,这个代码没有太多的用处。 如果存在的话,那么这个条件是否应该被颠倒是一个风格问题,并且应该只包含一个非空的部分。

在这种情况下,这是一个简单的条件,所以风格明智的倒置它可能会更好,但是如果条件更复杂,可以更清楚地写这种方式。 例如,这个:

 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 } 

来自评论的一个更好的例子(感谢本):

 if (not_found) { ; } else { // do something } 

与:

 if (!not_found) { // do something } 

使用哪种方法在很大程度上取决于正在比较什么,有多less条款,条款是如何嵌套的,甚至是所涉及的variables/函数的名称。

当你可能使用这个的另一个例子是,当你有一组if..else语句来检查一个值的范围,并且你想要在代码中logging什么东西不应该发生在一个特定的范围:

 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包含空白的if ,它对读者说:“是的,我解释了这一点,在这种情况下什么也不应该发生”。

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

它被称为空声明

从6.8.3expression式和空语句 :

空语句(仅由分号组成)不执行任何操作。

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

没有目的。 这是一个空话。 如果a不是1 ,那么开发者可能会想要做些什么,在这种情况下,代码会是这样的(尽pipe这个代码仍然可以省略):

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

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


但是请注意,如果这是C ++(标签还不清楚),则可能会出现atypes的operator==被重载并且可能会观察到一些副作用。 这意味着代码是疯了。

这就是所谓的空声明。 这是一种expression错误的expression语句。

有时在if-else语句中使用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语句是必需的。 你也可以重写它

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

有时,在使用goto语句的情况下,特别是在less数情况下需要空语句。 例如在C中的声明不是语句。 如果你想在某个声明之前把程序控制传递给某个点,你可以在声明之前放置一个标签。 然而,在C中,标签可能只在语句之前放置。 在这种情况下,您可以在声明之前放置带有标签的空语句。 例如

 Repeat:; ^^^ int a[n]; //.... n++; goto Repeat; 

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

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

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

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

正如许多人所说的 – 它什么都不做。

为什么呢? 这是一个可能性…

我厌倦了我的团队不好的编码器检查函数的返回值。

因此,我们使用GCC编译器在Linux中进行开发,我将__attribute__((warn_unused_result))到所有types函数的声明中。 另请参阅此问题的MS VC等效。

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

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

一个; 是什么也不做的空声明 。 它通常用在很长的if / else链中,如:

 if (a == 1) { // Do nothing. ; } else if (...) { ... } else if (...) { ... } 

这也可以写成:

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

后者增加了另一个级别的缩进,但国际海事组织,它更清楚。 但是如果有多个没有代码的分支,空语句有时可以用来避免过多的缩进。

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

 if (a == 1) {} 

从技术上讲,如果你想直接使用expression式语句 ,你只需要分号:

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

所以写{;}是多余的,只是一个可疑的说明目的。

另一个来自C语言标准的例子是null语句用来提供一个空的循环体:

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

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

; 本身就是一个空话 。 如果a是一个初始化的非指针types,那么

if(a==1){;}

在C中总是没有任何操作。使用大括号可以增加额外的权重,断言没有错字。 也许有一个直接在它下面,如果不是1就执行。

它基本上是一个空/空的陈述,它什么都不做 ,在自然界中是预期的良性(没有错误)。

C规格草案N1570澄清:

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

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

分号本身就是一个陈述,是空的陈述。

请注意, if(1) {;}if(1) {}这两个代码在生成的gcc指令中没有差异 。

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

通常情况下,虽然我明确表示它是一个debugging标记

 if( (a==1) && (b==2) && (c==3) && (d==4) ){ int debug=1; } 

否则,我最终会遇到一些怪异的代码,即使对我来说也是毫无意义的。

但是,这不能保证这是什么。

; 是一个空的声明noop

它的目的是什么?

有时候我们只是想比较一下在这种情况下,a和1是否相等。对于像integer这样的基本types,这将设置条件寄存器,所以如果在if(a> 1)或if(a <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) ,正好在写入(a == 1)的地方。

您可能已经知道分号是一个空的陈述。 关于“这个分号用于什么目的”的实际问题,答案是(除非这个代码的作者想用一些奇怪的表情来使代码活跃起来),它根本没有任何用处 。 也就是说, {;}任何上下文 (在预期的语句中,我认为是{;}可以使用的唯一位置)完全等价于{} 。 分号的存在将具有0个组成语句的复合语句转换为具有1个组成语句的复合语句,这是一个空语句,但就语义而言这两个语句是等价的。

我会添加一个个人的观点,为了可读性而不被读者忽略, {;}并不比{} (如果是,那么也许{;;;;;;;;}还是更好),虽然两者都比孤独好很多; (因此,语言本来不会变得更好,因为这是空话,因为用{}replace它总是有利的)。