1

I was looking at this block of code:

int main() {
    void *labels[] = { &&label1, &&label2 };

    goto *labels[1];

  label1:
    printf("Label 1\n");

  label2:
    printf("Label 2\n");

    return 0;
}

I was wondering if this is a normal thing and can be expected in any compiler.

  • It is not a standard C code. – Vlad from Moscow Sep 08 '22 at 18:54
  • 1
    Welcome to SO. Why would you want to use such a beast? While it might be debatable to what extent a `goto` is acceptable, using it with variables holding the address would clearly be a no-go in any code review. – Gerhardh Sep 08 '22 at 18:54
  • [`warning: taking the address of a label is non-standard [-Wpedantic]`](https://godbolt.org/z/he6j4b4sY) – Avi Berger Sep 08 '22 at 18:55
  • @AviBerger There's no use case for it? – FariyaAchhab Sep 08 '22 at 19:00
  • It is non-standard. It cannot be expected in any compiler unless it is specifically documented that that compiler has this "not officially in the language" feature. There could be a use case for it. But it's non-portable & likely won't be recognized by others looking at the code. You'd need to make a really strong case to try it, rather than using another approach; & would still likely get shot down for trying such a stunt. – Avi Berger Sep 08 '22 at 19:09
  • 2
    @Gerhardh: CPython uses this to achieve, IIRC, roughly a 15-20% speed up by dramatically reducing bytecode dispatch overhead relative to the "infinite loop around a `switch`" used when computed-gotos aren't available. Branch prediction on the `switch` is essentially useless, but there is a tendency for certain bytecodes to repeatedly be followed by other specific bytecodes (sometimes the same, sometimes a different code), and since branch prediction typically works on a per-instruction level, each opcode ends up with its own (useful) branch prediction, which helps a lot. – ShadowRanger Sep 08 '22 at 19:40

1 Answers1

0

it's one of the GCC compilers features , refer to labels as Values in GCC manual , they clearly state that :

You can get the address of a label defined in the current function (or a containing function) with the unary operator ‘&&’. The value has type void *. This value is a constant and can be used wherever a constant of that type is valid. For example:

void *ptr;
/* … */
ptr = &&foo;

where foo is just a label , so yeah , you can deal with labels as addresses in GCC compiler according to the manual.

even they have this example that is nearly same as yours as they stated that :

One way of using these constants is in initializing a static array that serves as a jump table:

 static void *array[] = { &&foo, &&bar, &&hack };

Then you can select a label with indexing, like this:

 goto *array[i];

but it's a feature in GCC compiler , so whatever the compiler you use , refer to its manual and you should know if this feature is supported or not.

but also remember that , it's not a good practice to use label and goto in your code if you are coding for critical system which sticks to strict rules as according to MISRA C in section 8.15 Control flow , they clearly stated that :

Rule 15.1 The goto statement should not be used

so then it might be better to say that using goto is a fine practice when used thoughtfully and judiciously so long as it is not applied in a codebase that observes such strict guidelines.

abdo Salm
  • 1,678
  • 4
  • 12
  • 22
  • 1
    but even the linux kernel has code contributed by professionals that use goto – FariyaAchhab Sep 08 '22 at 19:08
  • @FariyaAchhab , notice that MISRA C also stated in **rule 17.1** that `The features of shall not be used` , but this header file is used very often , notice that MISRA C is a specification to C code standard that's meant to be used when implementing critical systems , many embedded systems projects rely on MISRA C rules. so it's nothing that you must stick to , but it's advisory especially when coding for a critical system. – abdo Salm Sep 08 '22 at 19:18