2010-04-26 35 views
7

Đối với đoạn mã C++ dưới đây:mảng tĩnh được xác định với kích thước không xác định, dấu ngoặc trống?

class Foo { 
    int a[]; // no error 
}; 

int a[];  // error: storage size of 'a' isn't known 

void bar() { 
    int a[]; // error: storage size of 'a' isn't known 
} 

tại sao không phải là biến thành viên gây ra một lỗi quá? và ý nghĩa của biến thành viên này là gì?

Tôi đang sử dụng phiên bản gcc 3.4.5 (đặc biệt mingw-vista) thông qua CodeBlocks 8.02.

Mở Visual Studio Express 2008 - Microsoft (R) C/C++ Compiler Tối ưu hóa 15.00.30729.01 cho 80x86, tôi đã thông báo sau:

class Foo { 
    int a[]; // warning C4200: nonstandard extension used : zero-sized array in struct/union - Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array 
}; 

int a[]; 

void bar() { 
    int a[]; // error C2133: 'a' : unknown size 
} 

Bây giờ, điều này cần một số Giải thích quá.

+0

Chú thích đề cập đến "mảng tĩnh". Các "mảng tĩnh" này nằm trong câu hỏi của bạn ở đâu? Tôi không thấy một tham chiếu duy nhất cho bất kỳ "mảng tĩnh" nào. – AnT

+0

Tôi có nghĩa là các mảng được phân bổ tĩnh. Vui lòng chỉnh sửa câu hỏi nếu bạn thấy cần thiết. Cảm ơn bạn. –

Trả lời

6

C99 hỗ trợ thứ được gọi là thành viên mảng 'linh hoạt' được phép là thành viên cuối cùng của cấu trúc. Khi bạn tự động phân bổ cấu trúc như vậy, bạn có thể tăng số tiền được yêu cầu từ malloc() để cung cấp bộ nhớ cho mảng.

Một số trình biên dịch thêm phần này làm phần mở rộng cho C90 và/hoặc C++.

Vì vậy, bạn có thể có mã như sau:

struct foo_t { 
    int x; 
    char buf[]; 
}; 


void use_foo(size_t bufSize) 
{ 
    struct foo_t* p = malloc(sizeof(struct foo_t) + bufSize); 

    int i; 

    for (i = 0; i < bufSize; ++i) { 
     p->buf[i] = i; 
    } 
} 

Bạn không thể định nghĩa một struct với một thành viên mảng linh hoạt trực tiếp (như là một địa phương hoặc một biến toàn cầu/tĩnh) như trình biên dịch sẽ không biết có bao nhiêu bộ nhớ để phân bổ cho nó.

Tôi thành thật không chắc chắn cách bạn dễ dàng sử dụng điều như vậy với toán tử new của C++ - Tôi nghĩ bạn phải cấp phát bộ nhớ cho đối tượng bằng cách sử dụng malloc() và sử dụng vị trí new. Có thể sử dụng một số lớp/cấu trúc quá tải cụ thể của operator new ...

2
class Foo { 
    int a[]; // OK in C, invalid in C++. Does not work with inheritance. 
}; // Idea is that structure is "extended" indefinitely by an array. 
    // May work on your compiler as an extra feature. 

int a[];  // error in C and C++: storage size of 'a' isn't known 

void bar() { 
    int a[]; // error in C and C++: storage size of 'a' isn't known 
} 

extern int a[]; // OK: storage size may be declared later. 

int a[5]; // declaration of size before use. 

Loại mảng có kích thước không xác định chưa hoàn chỉnh. 8.3.4/1:

Nếu biểu thức hằng số bị bỏ qua, loại định danh của D là "chuỗi khai báo kiểu danh sách-khai báo kiểu không xác định của T", một kiểu đối tượng không hoàn chỉnh.

Nó phải được hoàn thành để tham gia định nghĩa, tức là định nghĩa a phải chứa thông số hoặc kích thước kích thước có kích thước được chỉ định.

+1

Tôi không hiểu ý kiến ​​"phải được hoàn tất trước khi sử dụng". Nó là hoàn toàn hợp pháp để * sử dụng * một mảng kích thước không xác định trong C++. Bạn không thể áp dụng 'sizeof' cho nó, nhưng bạn có thể truy cập một cách hợp pháp các phần tử của nó. – AnT

+0

@Andrey: Đối số hàm được khai báo là một mảng có kích thước không xác định có loại 'T *'. Nó là một phân rã sang loại khác. Có một ví dụ khác mà tôi nên biết không? Câu trả lời của bạn dường như không hiển thị bất kỳ câu trả lời nào. – Potatoswatter

+0

Tôi không nói về các đối số chức năng, đó là một câu chuyện hoàn toàn khác. Tôi đã đề cập đến khai báo 'extern int a []' trong ví dụ của bạn. Khi bạn khai báo một mảng như vậy, bạn có thể * sử dụng * nó rồi. Tôi thấy bạn đã xóa tham chiếu đến "sử dụng". – AnT

0

Chúng tôi đã sử dụng điều này để biểu thị một bản ghi độ dài thay đổi của một số loại. Một cái gì đó giống như một tập tin tiêu đề có thông tin về bao nhiêu cấu trúc để làm theo, theo sau là dữ liệu chính nó. Đó là một mảng chiều dài biến và tôi đã tìm thấy nó không được hỗ trợ tốt giữa các trình biên dịch. Một số muốn mảng []; và một số muốn mảng [0]; (phong cách cũ).

11

ngôn ngữ C++ cho phép bỏ qua kích thước mảng chỉ trong không xác định tờ khai

extern int a[]; // non-defining declaration - OK in C++ 

int a[]; // definition - ERROR in C++ 

int a[5]; // definition - OK, size specified explicitly 
int a[] = { 1, 2, 3 }; // definition - OK, size specified implicitly 

Non-tĩnh decarations thành viên lớp luôn cần thiết để xác định kích thước mảng

struct S { 
    int a[]; // ERROR in C++ 
}; 

trong khi thành viên lớp tĩnh decarations có thể bỏ kích thước

struct S { 
    static int a[]; // OK in C++ 
}; 

(định nghĩa của cùng một thành viên sẽ, tất nhiên, phải chỉ định kích thước).

Bất kỳ sai lệch nào từ hành vi này chỉ có thể được giải thích bằng cách mở rộng hành vi không chuẩn của trình biên dịch của bạn. Có lẽ bạn nên chỉ định một số cài đặt trình biên dịch bổ sung để làm cho nó hoạt động theo kiểu thời trang hơn.

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