我很想在没有血淋淋的内存布局细节的情况下解释这一点(相信我,他们得到very使用 VLA 时的血淋淋;有关详细信息,请参阅@Ulfalizer 的答案)。
因此,最初,在 C89 中,必须在块的开头声明所有变量,如下所示:
{
int a = 1;
a++;
/* ... */
}
这直接暗示了一件非常重要的事情:一个块==一组不变的变量声明。
C99改变了这一点。在其中,您可以在块的任何部分声明变量,但声明语句仍然与常规语句不同。
事实上,为了理解这一点,您可以想象所有变量声明都隐式移动到声明它们的块的开头,并且对于它们之前的所有语句都不可使用。
那只是因为一个块 == 一组声明规则仍然成立。
这就是为什么你不能“跳过声明”。声明的变量仍然存在。
问题是初始化。它不会被“移动”到任何地方。因此,从技术上讲,对于您的情况,以下程序可以被认为是等效的:
goto later;
int a = 100;
later:
printf("%d", a);
and
int a;
goto later;
a = 100;
later:
printf("%d", a);
正如你所看到的,声明仍然存在,只是跳过了初始化。
这不适用于 VLA 的原因是它们是不同的。简而言之,这是因为这是有效的:
int size = 7;
int test[size];
与所有其他声明不同,VLA 的声明在声明它们的块的不同部分中表现不同。事实上,VLA 可能具有完全不同的内存布局,具体取决于它的声明位置。你只是无法将它“移动”到你刚刚跳过的地方之外。
你可能会问:“好吧,那为什么不这样做,使声明不受goto
“?好吧,你仍然会遇到这样的情况:
goto later;
int size = 7;
int test[size];
later:
您实际上希望这做什么?
因此,禁止跳过 VLA 声明是有原因的 - 通过完全禁止它们来处理上述情况是最合乎逻辑的决定。