2012-06-24 36 views
8

Tôi tự hỏi tại sao tôi tiếp tục gặp lỗi error: flexible array member not at end of struct khi tôi gọi malloc. Tôi có một cấu trúc với một mảng chiều dài biến, và tôi tiếp tục nhận được lỗi này.Nguyên nhân của thành viên mảng linh hoạt không phải ở cuối lỗi cấu trúc là gì?

Các struct là,

typedef struct { 
    size_t N; 
    double data[]; 
    int label[]; 
} s_col; 

và cuộc gọi đến malloc là,

col = malloc(sizeof(s_col) + lc * (sizeof(double) + sizeof(int))); 

Đây có phải là cuộc gọi đúng để malloc?

Trả lời

14

Bạn chỉ có thể có một thành viên mảng linh hoạt trong cấu trúc và phải luôn là thành viên cuối cùng của cấu trúc. Nói cách khác, trong trường hợp này bạn đã đi sai trước khi bạn gọi malloc, đến mức thực sự không có cách nào để gọi malloc chính xác cho cấu trúc này.

Để làm những gì bạn dường như muốn (mảng của cùng một số datalabel thành viên), bạn có thể xem xét một cái gì đó như:

struct my_pair { 
    double data; 
    int label; 
}; 

typedef struct { 
    size_t N; 
    struct my_pair data_label[]; 
}; 

Lưu ý rằng điều này là hơi khác nhau mặc dù: thay vì một loạt các double s theo sau là một mảng là int s, nó cung cấp cho bạn một mảng double theo sau là một int, sau đó là double tiếp theo, tiếp theo int, v.v. Cho dù điều này là đủ gần để cùng hay không sẽ phụ thuộc vào cách bạn đang sử dụng dữ liệu (ví dụ, để đi đến một chức năng bên ngoài dự kiến ​​một mảng liền kề, có thể bạn sẽ phải làm những việc khác nhau).

3
typedef struct { 
    size_t N; 
    double data[]; 
    int label[]; 
} s_col; 

Bạn không thể có thành viên mảng linh hoạt (double data[]) ở giữa. Hãy xem xét kích thước mảng được mã hóa cứng hoặc double *data

+0

Tôi không hiểu, tôi được dạy rằng "T * var" giống với "T var []" – spectre

+1

@ lukasz1985: Điều bạn nói là đúng trong bối cảnh đối số hàm, nơi bạn có thể chỉ định " một đối số thao tác mảng "được thực hiện bằng kỹ thuật bằng con trỏ. Thông thường (tức là ở đây) mảng là một mảng, và con trỏ là một con trỏ. – stan423321

2

Với định nghĩa struct và con trỏ để bắt đầu cấu trúc, trình biên dịch C có thể truy cập bất kỳ thành viên nào của cấu trúc mà không phải truy cập bất kỳ thứ gì khác. Vì vị trí của mỗi mục trong cấu trúc được xác định bởi số lượng và loại mục trước đó, nên việc truy cập bất kỳ mục nào yêu cầu số lượng và loại của tất cả các mục trước đó được biết. Trong trường hợp cụ thể trong đó mục cuối cùng là mảng, điều này không có khó khăn cụ thể khi truy cập một mục trong một mảng yêu cầu biết nơi bắt đầu mục (yêu cầu phải biết số và loại trước các mục, thay vì số lượng mục trong bản thân mảng) và chỉ mục mục (mà trình biên dịch có thể giả định là nhỏ hơn số lượng các mục mà không gian tồn tại, mà không cần phải biết gì về kích thước mảng). Nếu một thành viên mảng linh hoạt xuất hiện ở bất kỳ nơi nào khác ngoài kết thúc của một cấu trúc, thì vị trí của bất kỳ mục nào theo sau nó sẽ phụ thuộc vào số lượng các mục trong mảng - thứ mà trình biên dịch sẽ không biết.

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