2012-02-09 37 views
24

Tôi gặp lỗi khi cố tạo một mảng từ các biến mà tôi đã khai báo.mảng C++ - biểu thức phải có giá trị không đổi

int row = 8; 
int col= 8; 
int [row][col]; 

Tại sao tôi nhận được lỗi này:

expression must have a constant value.

+0

Điều gì mong đợi 'int [row] [col];' để làm, chính xác? –

+0

Sách C++ tốt được liệt kê ở đây: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list –

+5

Không chỉnh sửa mã của câu hỏi của bạn với bản sửa lỗi; điều này làm cho câu hỏi của bạn vô cùng khó hiểu đối với người đọc trong tương lai. – ildjarn

Trả lời

14

C++ không cho phép giá trị không đổi đối với kích thước của một mảng. Đó chỉ là cách nó được thiết kế.

C99 cho phép kích thước của một mảng là một biến, nhưng tôi không chắc nó có được phép cho hai thứ nguyên hay không. Một số trình biên dịch C++ (gcc) sẽ cho phép điều này như là một phần mở rộng, nhưng bạn có thể cần phải bật tùy chọn trình biên dịch để cho phép nó.

Và tôi gần như bỏ lỡ nó - bạn cần phải khai báo một tên biến, không chỉ là kích thước mảng.

+0

"nhưng tôi không chắc chắn nó được phép cho hai chiều" - nó được. Đối với C, như bạn đã chú ý, không phải cho C++. – hvd

+0

@hvd, cảm ơn bạn đã làm rõ. Sự tiếp xúc của tôi với C thuần khiết những ngày này thật đáng buồn. –

29

Khi tạo một mảng như vậy, kích thước của nó phải không đổi. Nếu bạn muốn có một mảng động có kích thước, bạn cần phải phân bổ bộ nhớ cho nó trên đống và bạn cũng sẽ cần phải giải phóng nó với delete khi bạn đã hoàn tất:

//allocate the array 
int** arr = new int*[row]; 
for(int i = 0; i < row; i++) 
    arr[i] = new int[col]; 

// use the array 

//deallocate the array 
for(int i = 0; i < row; i++) 
    delete[] arr[i]; 
delete[] arr; 

Nếu bạn muốn có một kích thước cố định, sau đó họ phải được khai báo const:

const int row = 8; 
const int col = 8; 
int arr[row][col]; 

Ngoài ra,

int [row][col]; 

thậm chí không cung cấp một tên biến.

+4

Có thể hiển thị cách xóa bộ nhớ, eh? ;) – monoceres

8

Tiêu chuẩn yêu cầu độ dài mảng là giá trị được tính toán tại thời gian biên dịch sao cho trình biên dịch có thể phân bổ đủ không gian trên ngăn xếp. Trong trường hợp của bạn, bạn đang cố gắng đặt độ dài mảng thành một giá trị không xác định tại thời gian biên dịch. Có, tôi biết rằng nó có vẻ rõ ràng rằng nó nên được biết đến trình biên dịch, nhưng đây không phải là trường hợp ở đây. Trình biên dịch không thể đưa ra bất kỳ giả định nào về nội dung của các biến không liên tục. Vì vậy, hãy truy cập:

const int row = 8; 
const int col= 8; 
int a[row][col]; 

UPD: một số trình biên dịch thực sự sẽ cho phép bạn tắt tính năng này. IIRC, g ++ có tính năng này. Tuy nhiên, không bao giờ sử dụng nó bởi vì mã của bạn sẽ trở thành un-portable trên các trình biên dịch.

+1

Câu trả lời ngắn gọn và chính xác nhất. –

4

Khi bạn khai báo một biến như ở đây

int a[10][10]; 

bạn đang nói ++ biên dịch C mà bạn muốn 100 số nguyên liên tiếp được phân bổ trong bộ nhớ của chương trình khi chạy. Trình biên dịch sau đó sẽ cung cấp cho chương trình của bạn để có nhiều bộ nhớ có sẵn và tất cả là tốt với thế giới.

Tuy nhiên, nếu bạn nói với trình biên dịch

int x = 9001; 
int y = 5; 
int a[x][y]; 

trình biên dịch không có cách nào để biết có bao nhiêu bộ nhớ bạn đang thực sự sẽ cần ít thời gian chạy mà không làm rất nhiều phân tích rất phức tạp để theo dõi mọi nơi cuối cùng trong đó các giá trị của x và y thay đổi [nếu có]. Thay vì hỗ trợ các mảng có kích thước biến như vậy, C++ và C mạnh mẽ đề xuất nếu không yêu cầu hoàn toàn bạn sử dụng malloc() để phân bổ không gian theo cách thủ công mà bạn muốn.

TL; DR

int x = 5; 
int y = 5; 
int **a = malloc(x*sizeof(int*)); 
for(int i = 0; i < y; i++) { 
    a[i] = malloc(sizeof(int*)*y); 
} 

một bây giờ là một mảng 2D kích thước 5x5 và sẽ hoạt động giống như int a [5] [5]. Bởi vì bạn đã phân bổ bộ nhớ theo cách thủ công, C++ và C yêu cầu bạn xóa nó bằng tay quá ...

for(int i = 0; i < x; i++) { 
    free(a[i]); // delete the 2nd dimension array 
} 
free(a); // delete a itself 
+1

Câu trả lời của bạn không hợp lệ C++: bạn đang dựa vào một chuyển đổi ngầm từ 'void *' thành 'int *' và 'int **'. Và tất nhiên, nếu bạn thêm một diễn viên, nó vẫn còn phong cách xấu để sử dụng khá nhiều 'malloc' ở tất cả. – hvd

-2

Không cần phải liên tục, lý do mã của anh ta ở trên là sai vì anh ấy cần để bao gồm tên biến trước khi khai báo.

int row = 8; 
int col= 8; 
int x[row][col]; 

Trong Xcode sẽ biên dịch và chạy mà không có bất kỳ vấn đề, trong M $ C++ biên dịch trong .NET nó sẽ không biên dịch, nó sẽ phàn nàn rằng bạn không thể sử dụng một const không đen để khởi tạo mảng, nhu cầu kích thước được biết tại thời gian biên dịch

7

Bạn có thể sử dụng #define làm giải pháp thay thế, không giới thiệu vectơ và malloc và bạn vẫn đang sử dụng cùng cú pháp khi xác định mảng.

#define row 8 
#define col 8 

int main() 
{ 
int array_name[row][col]; 
} 
Các vấn đề liên quan