为什么在函数末尾放置标签时必须包含分号?

问题描述

带有 goto 错误处理程序的简单函数

void checkFile(char *name)
{
    FILE *fp = fopen(name,"r");
    if(NULL == fp)
    {
        fprintf(stderr,"Could not open %s\n",name);
        goto end;
    }

    // use fp...

    fclose(fp);
    end:
    ;
}

请注意,如果我删除 end: 后无用的分号,该函数将无法编译。

在海湾合作委员会:

error: expected primary-expression before '}' token
   16 | }

在 MSVC 上:

error C2143: Syntax error: missing ';' before '}'

所以,我知道 C 标准确实说 goto 关键字的目标需要 § 6.8.6.1 p 2 中的语句:

goto 语句导致无条件跳转到由封闭函数中的命名标签前缀的语句

然而,错误存在只是因为标签存在;如果我删除 goto 关键字,标签本身仍然被视为错误并且不会编译。我阅读了标准中关于“带标签的语句”(第 6.8.1 节)的部分,但仍然没有找到任何可以解释这种奇怪约束的内容

解决方法

在 C 中,标签可以放在语句之前。所以如果没有语句,你可以放置一个空语句。

来自 C 标准(6.8.1 标记语句)

labeled-statement:
    identifier : statement
    case constant-expression : statement
    default : statement

And(6.8.3 表达式和空语句)

expression-statement:
    expressionopt ;

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

在 C++ 声明中与 C 相对的也是语句。因此,在 C++ 中,您可以在声明之前放置一个标签。

这里是演示程序。

C 程序。

#include <stdio.h>

int main(void) 
{
    goto End;
    
    End:;
    const char *bye = "Bye";
    
    puts( bye );
    
    return 0;
}

程序输出为

Bye

C++ 程序

#include <iostream>

int main() 
{
    goto End;
    
    End:
    const char *bye = "Bye";
    
    std::cout <<  bye << '\n';

    return 0;
}

程序输出为

Bye

注意在C程序中label后面放了一个空语句

End:;

没有它,编译器会报错。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...