为什么有人会用这个?
if(a==1){;}
没有声明,只有一个分号,并且它不会抛出错误。 这个分号的用途是什么?
答案 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 澄清:
- 表达式是可选的: 表达式[opt];
- 空语句(仅由分号组成)不执行任何操作。
醇>
另一方面,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}虽然两者都比单独的{;;;;;;;;}
要好得多(因此,在没有允许;
作为空语句的情况下,语言会更好,因为将其替换为;
总是有利的。)