2010-07-24 30 views
6

Tôi có đoạn mã sau:C++ int a [n] làm việc trong g ++ nhưng không phải với vs2008

... 
int n; 
cin >> n; 
int numbers[n]; 
... 

Nó được biên soạn với NetBeans trên Mac sử dụng g ++ (tôi nghĩ) và nó không biên dịch sử dụng VS2008 trên Các cửa sổ. Tại sao nó khó khăn như vậy để làm cho nó hoạt động với mọi trình biên dịch? Kích thước của mảng được biết trước khi phân bổ nó.

CHỈNH SỬA: Tôi biết về std::vector. Trên thực tế đây là một phần của một bài tập về nhà và tôi bắt đầu nó tại nơi làm việc trên một mac, sau đó về nhà và đã rất ngạc nhiên rằng nó đã không làm việc trên VS2008. Cảm ơn tất cả các câu trả lời. Nhưng tôi vẫn thấy nó hợp lý rằng nếu trình biên dịch có thể tạo ra một số mã như alloc(123) nơi giá trị 123 được mã hóa cứng, tại sao nó không thể tạo ra một cái gì đó như alloc(n) nơi bạn nhận được n từ địa chỉ bộ nhớ giữ int n hoặc gì đó. Nó chỉ có vẻ hợp lý hơn để cho phép một cái gì đó như thế này theo mặc định.

+4

tại sao không sử dụng một số công cụ thực tế cpp như 'std :: vector ' cho rằng –

+1

@RC: Đó là câu trả lời hay - hãy biến nó thành một thực tế! –

+1

@Drew: done;) thanks –

Trả lời

16

Mặc dù kích thước của mảng được biết trước khi nó được cấp phát, nó vẫn chưa được biết cho đến khi chạy. Điều này được gọi là mảng độ dài biến (VLA) và là một C99ism, được hỗ trợ trong g ++ bởi một phần mở rộng được kích hoạt theo mặc định. Để được rõ ràng, điều này không phù hợp C++ 98/03, và do đó Visual C++ là tốt trong quyền của mình để từ chối nó.

Nếu bạn thực sự muốn định kích thước động thời gian chạy, hãy phân bổ trên heap (qua new []). Điều đó sẽ làm việc ở khắp mọi nơi, và như một tiền thưởng, bảo vệ bạn khỏi tràn ngăn xếp.

+7

Thực ra, không sử dụng 'mới []'. Sử dụng 'std :: vector'. – GManNickG

+0

@ GMan - Tôi hết lòng đồng ý! Trong sự vội vàng của tôi, tôi đã bỏ qua đề cập đến tùy chọn đó, nhưng không muốn câu trả lời của cherrypick RC vào thời điểm này! :) –

+0

Tôi đã phải làm việc xung quanh thiếu này bản thân mình, mặc dù, trong khi thực hiện cấu trúc dữ liệu chèn/xóa các thuật toán. Chúng được sử dụng rất nhiều, bao gồm cả trong các vòng bên trong, vì vậy chắc chắn điểm nóng hiệu suất.Tôi cần thiết để xây dựng một "kế hoạch" (không bắt đầu thay đổi các nút cho đến khi bạn biết op sẽ thành công - đảm bảo tự nhất quán về sự thất bại). Cuối cùng, tôi đã sử dụng một danh sách liên kết trên ngăn xếp, xây dựng một mục tại một thời điểm bằng cách sử dụng các cuộc gọi đệ quy (lấy các cơn đau để giảm thiểu chi phí cuộc gọi). Một VLA có lẽ sẽ dễ dàng hơn. – Steve314

12

Do kích thước của mảng phải là hằng số thời gian biên dịch theo chuẩn C++ (xem 8.3.4 §1).

1

Hỗ trợ cho Vlas là không có mặt trong Visual Studio 2008.

+7

Hoặc bằng C++. – GManNickG

12

tại sao không sử dụng một số công cụ thực cpp như std::vector<int> cho rằng

2

Something tương tự có thể thực hiện với ne

int* numbers = (int*)alloca(n * sizeof(int)); // equivalent to int numbers[n] 

đây không phải là chức năng được đề xuất, nhưng nếu được sử dụng cẩn thận, sẽ cho kết quả chính xác như nhau.

+4

Và với đầu vào được chế tác cẩn thận, người dùng có thể tràn ngăn xếp và giành điểm số cho kẻ xấu. –

+0

@Franci, bạn không có gì tốt hơn để làm hơn là thiết kế "đầu vào được chế tác cẩn thận" cho chương trình cụ thể này không? :) Thử tốt hơn http://www.crackmes.de – ruslik

+0

Có sự khác biệt quan trọng giữa VLA và alloca(). VLA tồn tại trong phạm vi khai báo của chúng, trong khi khối alloca() vẫn tồn tại trong phạm vi của hàm *. Khai báo một VLA trong một cơ thể vòng lặp sử dụng do đó ngăn xếp ít hơn như làm một alloca trong cơ thể. Vì vậy, nếu bạn tìm hiểu về kích thước mảng cần thiết trong vòng lặp, alloca có thể không làm việc cho bạn. –

2

Bằng cách đặt thứ nguyên mảng phải là một biểu thức liên tục có giá trị lớn hơn hoặc bằng một. Biểu thức liên tục trong các hằng số nghĩa đen, số đếm hoặc các đối tượng const của kiểu không thể tách rời được tự khởi tạo từ các biểu thức const. Một biến không const có giá trị không được biết cho đến khi thời gian chạy không thể được sử dụng để xác định kích thước của một mảng.

Nhưng phiên bản trình biên dịch tôi sử dụng cho phép cách bạn đề cập.

Các vấn đề liên quan