I am determined to explain this without detailed memory information (believe me, they are very hot when using VLAs, see @Ulfalizer answer for details).
So, initially on C89 it was mandatory to declare all variables at the beginning of the block, for example:
{ int a = 1; a++; }
This directly implies a very important thing: one block == one immutable set of variable declarations.
C99 changed that. In it, you can declare variables in any part of the block, but declarations of declarations are still different from ordinary operators.
In fact, to understand this, you can imagine that all variable declarations are implicitly moved to the beginning of the block, where they are declared and inaccessible to all operators that pursue them.
This is simply because one block == another set of ad rules is saved.
That is why you cannot "jump over the declaration." The declared variable will still exist.
The problem is initialization. He does not "move" anywhere. So, technically for your case, the following programs can be considered equivalent:
goto later; int a = 100; later: printf("%d", a);
and
int a; goto later; a = 100; later: printf("%d", a);
As you can see, the declaration still exists, what is being skipped is initialization.
The reason this does not work with VLA is because they are different. In short, this is because it really is:
int size = 7; int test[size];
VLA announcements will, unlike all other announcements, behave differently in different parts of the block where they are declared. In fact, a VLA can have completely different memory layouts depending on where it is declared. You simply cannot βmoveβ it outside the place where you just jumped.
You may ask, "Well, then why not make the announcement not affected by goto "? Well, you still get cases like this:
goto later; int size = 7; int test[size]; later:
What do you really expect from this? ..
Thus, the prohibition of skipping VLA announcements exists for any reason - this is the most logical solution to consider such cases, simply banning them at all.