Govind Parmar
Govind Parmar

Reputation: 21572

Why must I include a semicolon when putting a label at the end of a function?

Simple function with a goto error handler:

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:
    ;
}

Notice, if I remove the useless semicolon after end: the function fails to compile.

On GCC:

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

On MSVC:

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

So, I understand that C standard does say that the destination of the goto keyword expects a statement in § 6.8.6.1 p 2:

A goto statement causes an unconditional jump to the statement prefixed by the named label in the enclosing function

However, the error exists just because the label exists; if I remove the goto keyword, the label itself is still treated as an error and won't compile. I read the standard's section on "Labeled statements" (§ 6.8.1) but still didn't find anything that explained this odd constraint.

Upvotes: 4

Views: 778

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 311186

In C a label may be placed before a statement. So if there is no statement you can place a null statement.

From the C Standard (6.8.1 Labeled statements)

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

And (6.8.3 Expression and null statements)

expression-statement:
    expressionopt ;

3 A null statement (consisting of just a semicolon) performs no operations.

Opposite to C in C++ declarations are also statements. So in C++ you may place a label before a declaration.

Here are demonstrative programs.

C program.

#include <stdio.h>

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

The program output is

Bye

C++ program

#include <iostream>

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

    return 0;
}

The program output is

Bye

Pay attention to that in the C program after the label there is placed a null statement

End:;

Without it the compiler will issue an error.

Upvotes: 6

Related Questions