Tôi đang trong tâm trạng cho việc giải thích này mà không Memory đẫm máu la chi tiết của bạn (tôi tin rằng, họ nhận được rất gory khi VLA được sử dụng; xem câu trả lời của @ Ulfalizer để biết chi tiết).
Vì vậy, ban đầu, trong C89, đó là bắt buộc phải khai báo tất cả các biến vào lúc bắt đầu của một khối, như thế này:
{
int a = 1;
a++;
/* ... */
}
này trực tiếp ám chỉ một điều rất quan trọng: một khối == một bộ không thay đổi các khai báo biến.
C99 đã thay đổi cài đặt này. Trong đó, bạn có thể khai báo các biến trong bất kỳ phần nào của khối, nhưng các câu lệnh khai báo vẫn khác với các câu lệnh thông thường. Trong thực tế, để hiểu điều này, bạn có thể tưởng tượng rằng tất cả các khai báo biến được chuyển hoàn toàn đến đầu khối, nơi chúng được khai báo và không có sẵn cho tất cả các câu lệnh đặt trước chúng.
Điều đó đơn giản chỉ vì khối một == một bộ khai báo quy tắc vẫn giữ.
Đó là lý do tại sao bạn không thể "nhảy qua tuyên bố". Biến được khai báo sẽ vẫn tồn tại.
Sự cố đang khởi tạo. Nó không nhận được "di chuyển" bất cứ nơi nào. Vì vậy, về mặt kỹ thuật, đối với trường hợp của bạn, các chương trình sau đây có thể được coi là tương đương:
goto later;
int a = 100;
later:
printf("%d", a);
và
int a;
goto later;
a = 100;
later:
printf("%d", a);
Như bạn có thể thấy, việc kê khai vẫn còn đó, những gì đang được bỏ qua là khởi tạo.
Lý do điều này không hoạt động với VLAs là chúng khác nhau.Tóm lại, đó là vì điều này hợp lệ:
int size = 7;
int test[size];
Tuyên bố VLAs sẽ không giống như tất cả các khai báo khác, hoạt động khác nhau ở các phần khác nhau của khối. Trong thực tế, VLA có thể có các bố trí bộ nhớ hoàn toàn khác nhau tùy thuộc vào vị trí nó được khai báo. Bạn không thể "di chuyển" nó ra khỏi nơi bạn vừa nhảy qua.
Bạn có thể hỏi, "được rồi, vậy tại sao không làm cho nó để tuyên bố sẽ không bị ảnh hưởng bởi goto
"? Vâng, bạn vẫn nhận được những trường hợp như thế này:
goto later;
int size = 7;
int test[size];
later:
gì bạn thực sự mong đợi điều này để làm ..
Vì vậy, cấm nhảy trên tờ khai VLA là có một lý do - đó là nhiều nhất? quyết định hợp lý để đối phó với các trường hợp như trên bằng cách đơn giản là cấm chúng hoàn toàn.
@ Mints97 Ah, vậy nếu các câu lệnh có các khối riêng của chúng ngay cả khi không có các câu lệnh phức hợp thì sao? Tôi cho rằng đó là câu trả lời sau đó :) quá xấu Tôi không thể chấp nhận ý kiến – MinecraftShamrock
bạn có ý gì? Điều gì sẽ xảy ra nếu các câu lệnh liên quan đến điều này? Và các khối và các câu lệnh phức hợp ít nhiều giống nhau, IIRC – Mints97
@ Mints97 Tôi có nghĩa là các biến được khai báo có điều kiện không được chuyển đến đầu của toàn bộ hàm nhưng chỉ bắt đầu từ "khối" có điều kiện mà chúng tồn tại ở bên phải? Vì vậy, một câu lệnh if không có câu lệnh ghép sẽ đại diện cho một khối như vậy. Tôi hiểu có đúng không? – MinecraftShamrock