Tại sao kích thước mảng toàn cầu phải là một hằng số nguyên?


8

Trong C ++, tôi đã thử khai báo một mảng toàn cầu có kích thước. Tôi đã nhận được lỗi:

mảng bị ràng buộc không phải là hằng số nguyên trước mã thông báo ']'

Nhưng khi tôi khai báo một mảng cùng loại trong main() hàm thì nó hoạt động tốt.

Tại sao có hành vi khác nhau ở đây?

int y=5;
int arr[y];         //When I comment this line it works fine

int main()
{
    int x=5;
    int arr2[x];        // This line doesn't show any error.
}

Chỉnh sửa: Nhiều người cho rằng câu hỏi này là một bản sao của Bắt lỗi "mảng bị ràng buộc không phải là hằng số nguyên trước ']' mã thông báo" . Nhưng câu hỏi đó không trả lời tại sao có hành vi khác nhau.


3
Ngay cả trong main, nó không hợp pháp, nó sử dụng phần mở rộng VLA.
Jarod42

4
Giới hạn của tất cả các mảng, trong C ++, cần phải có một giá trị, được biết đến trong quá trình biên dịch. Nếu mã đó, khi được đặt vào main"được chấp nhận" bởi trình biên dịch của bạn: bạn đang sử dụng tiện ích mở rộng trình biên dịch, cho phép biên dịch VLAs, ngay cả khi chúng không được hỗ trợ bởi tiêu chuẩn C ++.
Algirdas Preidžius

2
đừng nhầm lẫn "không có lỗi biên dịch" với "đang hoạt động tốt". Trong trường hợp này "hoạt động tốt" có nghĩa là mã của bạn dựa trên một trình biên dịch không chuẩn được cung cấp phần mở rộng, nghĩa là nó ổn, nhưng nó không di động được c ++
idclev 463035818

Tại sao không khai báo yxnhư const? Bạn có cần phải sửa đổi giá trị của yhay x? Hy vọng là không, bởi vì điều đó đặt ra nhiều câu hỏi về mức độ lớn arrarr2nên như thế nào - đặc biệt là với sự lặp lại trật tự khởi tạo. (Gợi ý: chúng phải là hằng số)
Wyck

Biên dịch chương trình của bạn với --std=c++17(hoặc --std=c++11nếu đó là trình biên dịch cũ hơn) và quá trình biên dịch sẽ thất bại.
einpoklum

Câu trả lời:


9

Cả hai ví dụ này đều không được định dạng trong C ++. Nếu một trình biên dịch không chẩn đoán cái sau, thì nó không phù hợp với tiêu chuẩn.

Tại sao có một hành vi khác nhau ở đây?

Bạn sử dụng một phần mở rộng ngôn ngữ cho phép các mảng tự động có độ dài thời gian chạy. Nhưng không cho phép các mảng tĩnh thời gian chạy. Mảng toàn cầu có lưu trữ tĩnh.

Trong trường hợp bạn đang sử dụng GCC, bạn có thể yêu cầu nó tuân thủ tiêu chuẩn bằng cách sử dụng tùy chọn dòng lệnh -pedantic. Đó là một ý tưởng tốt để làm như vậy để được thông báo về các vấn đề di động.


4

Kích thước của một mảng phải là một hằng số. Bạn có thể sửa lỗi này bằng cách khai báo yconst.

const int y=5;
int arr[y]; 

Về lý do tại sao điều này hoạt động main, g ++ không cho phép một mảng có chiều dài thay đổi trong phạm vi khối như một phần mở rộng. Nó không phải là C ++ tiêu chuẩn.


0

Cả hai không nên được sử dụng, một hoạt động vì (như @eerorika đã nói) mảng chiều dài tự động được phép trong thời gian chạy, nhưng mảng toàn cầu cần phải có bộ nhớ tĩnh.

Nếu bạn muốn khai báo một mảng có kích thước thay đổi (ví dụ: được đưa ra bởi std :: cin), bạn sẽ làm một cái gì đó dọc theo dòng:

int x;
std::cin >> x;
const int n = x;
float arr[n];

Nhưng bạn sẽ không thể đặt nó chỉ chứa các số không float arr[n] = {0}(nếu bạn cần thêm vào một giá trị trong mảng, không chắc chắn bạn đã đặt nó), bạn sẽ cần sử dụng một vòng lặp như thế

for(int i = 0; i < n; i++)
{
    arr[i] = 0;
}

1
Ví dụ của bạn vẫn bị hình thành mặc dù sử dụng const. Kích thước phải là một biểu thức hằng số thời gian biên dịch. Một cái gì đó mà bạn nhận được từ đầu vào thời gian chạy tất nhiên không đáp ứng điều đó.
eerorika

Tuyên bố rằng, Cả hai không nên sử dụng, không phù hợp. Người ta có thể muốn tránh sử dụng một mảng có độ dài thay đổi để viết mã C ++ di động. Người ta có thể muốn sử dụng một mảng có độ dài thay đổi để đạt được mục tiêu dự án mong muốn với chi phí tính di động. Các giá trị của những mục tiêu này là chủ quan và hoàn cảnh, và bạn không thể nói sự cân bằng nằm ở đâu cho người khác.
Eric Postpischil

@EricPostpischil Bạn đúng nhưng khi bạn sử dụng một biến có thể thay đổi, bạn có thể thay đổi nó và vì lý do an toàn, tốt hơn hết là giữ nó như một const
Jacob Korba

0

Hệ thống kiểu của C ++ xử lý các mảng giống như C này theo cách mà nó xác định arr2từ ví dụ về kiểu của bạn int[5]. Vì vậy, có số lượng phần tử của mảng là một phần của loại!

Điều này đặt ra một số ràng buộc về những gì bạn được phép sử dụng trong định nghĩa của các mảng giống như C. Tức là số này cần phải có lưu trữ tĩnh , cần phải bất biến và cần phải có sẵn tại thời điểm biên dịch .

Vì vậy, bạn có thể muốn thay đổi mã của mình thành một cái gì đó như sau, sẽ có một goodie khác. Nó khởi tạo mảng theo cách thích hợp:

int arr2[] = {0, 0, 0, 0, 0};   
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.