2012-12-28 49 views
7

thể trùng lặp:
Variably modified array at file scopemảng chiều dài Variable (VLA) trong C và C++

Tôi có một số khái niệm về VLA và hành vi của nó mà tôi cần phải làm rõ.

Afik từ C99 nó có thể tuyên bố VLA vào phạm vi địa phương:

int main(int argc, char **argv) 
{ 
    // function 'main' scope 
    int size = 100; 
    int array[size]; 
    return 0; 
} 

Nhưng nó bị cấm trong phạm vi toàn cầu:

const int global_size = 100; 
int global_array[global_size]; // forbidden in C99, allowed in C++ 

int main(int argc, char **argv) 
{ 
    int local_size = 100; 
    int local_array[local_size]; 
    return 0; 
} 

Đoạn mã trên khai báo một VLA trong C99 vì modifier const không tạo ra giá trị thời gian biên dịch. Trong C++ global_size là một giá trị biên dịch, do đó, global_array không trở thành VLA.

Điều tôi cần biết là: Lý do chính xác của tôi có đúng không? Hành vi mà tôi đã mô tả là chính xác?

Tôi cũng muốn biết: Tại sao VLA trong phạm vi toàn cầu không được phép? bị cấm cả trong C và C++? Lý do gì cho hành vi của mảng vào phạm vi toàn cầu và cục bộ là khác nhau?

+5

Giả sử VLA toàn cầu được cho phép. Khi nào kích thước (biến) của chúng thực sự được xác định? – cnicutar

+0

@cnicutar cũng ... giống như tất cả VLA, trong thời gian thực hiện, giống như các phạm vi khác. Tôi biết rằng đây không phải là câu trả lời, nhưng tôi muốn biết TẠI SAO. –

+1

http://stackoverflow.com/a/5052083/174605 – coelhudo

Trả lời

5

Có lý do của bạn là chính xác, đó là cách các dạng khai báo và định nghĩa mảng khác nhau được xem bởi C và C++.

Như những người khác đã nêu, VLA với độ dài biến thực sự (không phải const) trong phạm vi toàn cầu rất khó có ý nghĩa. Thứ tự đánh giá sẽ là gì, ví dụ: nếu biểu thức độ dài có liên quan đến một đối tượng của một đơn vị biên dịch khác không? C++ không có VLA, nhưng nó có khởi tạo động các đối tượng ở phạm vi tệp. Và điều này đã khiến bạn đau đầu, nếu bạn phải dựa vào thứ tự đánh giá.

Điều này để lại khoảng cách nhỏ cho C liên quan đến các biểu thức độ dài chứa đối tượng đủ điều kiện là const, điều này không được phép. Điều này xuất phát từ thực tế là các đối tượng như vậy không được coi là "biểu thức hằng số nguyên" theo tiêu chuẩn C. Điều này có thể thay đổi trong các phiên bản tương lai, nhưng đến nay ủy ban C không thấy cần thiết để cho phép một điều như vậy: có các hằng số enum đóng vai trò đó trong C. Giới hạn duy nhất của chúng là chúng được giới hạn ở int C, nó sẽ được tốt đẹp để có chúng size_t.

+0

Cuối cùng ai đó đã chứng minh đã đọc toàn bộ câu hỏi! (1 cho điều này) IMHO câu hỏi này không phải là [trùng lặp] (http://stackoverflow.com/questions/1712592/variably-modified-array-at-file-scope) bởi vì tôi đang tập trung vào các sự kiện khác. Cảm ơn lời giải thích và cảm ơn bạn đã trả lời hầu như tất cả các câu hỏi của tôi. –

1

Có sự khác biệt giữa bị cấm và không được phép. ;-)

Tính năng VLA được thiết kế để cho phép sử dụng không gian ngăn xếp cho một mảng cục bộ, để tránh việc sử dụng malloc cho phân bổ đống. Nó chủ yếu là một tối ưu hóa tốc độ.

Bây giờ bạn muốn sử dụng VLA ngoài chức năng. Tại sao? Không có nhiều để giành chiến thắng một cách nhanh chóng trong việc tránh một cuộc gọi malloc duy nhất trong khi bắt đầu chương trình. Và chúng ta phải sử dụng không gian ngăn xếp nào cho các biến có thời gian sống tĩnh?

3

Tôi nghĩ lý do cơ bản là biến toàn cầu có liên kết, kích thước của nó phải được biết tại thời gian biên dịch. Nếu không, làm thế nào có thể liên kết một chương trình?

biến cục bộ không có liên kết và VLA được cấp phát trên ngăn xếp, tăng tự động khi chương trình chạy.

2

C++ không hỗ trợ VLAs, dấu chấm câu. Lý do đoạn mã thứ hai hoạt động trong C++ là từ khóa const tạo ra một hằng số biên dịch trong C++; trong C, nó không.

C99 không hỗ trợ VLAs ngoài phạm vi khối, khoảng thời gian, bất kể bạn khai báo biến kích thước như thế nào. Lưu ý rằng C2011 làm cho VLA hỗ trợ tùy chọn.

+0

Có, tôi biết rằng 'const' từ khóa tạo ra một hằng số biên dịch-thời gian trong C + + và trong C nó không, tôi đã nhận xét này về câu hỏi. –

1

Vì vậy, đối với toàn cầu VLA của, một trong những vấn đề (có rất nhiều biến thể về chủ đề) có thể được hiển thị ở đây:

int size; 
int a; 
int v[size]; 
int b; 

.... trong tập tin khác:

extern int a; 
extern int b; 

Trình liên kết sẽ phải biết vị trí và liên quan với nhau tại thời gian liên kết hoặc sẽ không thể sửa chúng chính xác tại thời điểm tải.