What happens if you transfer control to a if(false) block by using goto?

Viewed 993

I've thought of following code by trying to solve a difficult 'nested-condition' problem:

goto error;
    
if (false)
{
error:
    cout << "error block" << endl;
}
else
{
    cout << "else block" << endl;
}

When I run this code, only error block is displayed, as expected (I guess?). But is this defined behavior across all compilers?

2 Answers

Yes, this is well defined. From stmt.goto#1

The goto statement unconditionally transfers control to the statement labeled by the identifier. The identifier shall be a label located in the current function.

There are some restrictions, e.g. a case label cannot cross a non-trivial initialization

goto error;
int i = 42;
error:       // error: crosses initialization of i

But these don't apply to your example. Also, in the case of crossing an initialization, this is a hard compiler error, so you don't have to worry about undefined behavior.


Note that once you jump to the case label error, you're effectively inside the true branch of the if condition, and it doesn't matter that you got there via a goto. So you're guaranteed that the else branch will not be executed.

My 5 cents:

If your compiler have optimizer, the code is reduced in following way:

// more code here
goto error; // this go directly to the label
    
if (false)
{
error:
    cout << "error block" << endl;
    // this skips else clause
}
else
{
    cout << "else block" << endl;
}
// more code here

So the compiled code become just this:

// more code here
{
    cout << "error block" << endl;
}
// more code here

Here is link to Godbolt:

https://gcc.godbolt.org/z/nY6E166Pz

(I did simplify the code a little bit so assembly is easier to read)

Related