2010-09-12 29 views
15

Trong C99 có mảng chiều dài thay đổi, và có thể có vòng tĩnh (và gõ vòng loại) trong tham số declarators mảng:C Parameter Mảng Declarators

void f(int i, int *a); 
void f(int i, int a[]); 
void f(int i, int a[i]); 
void f(int i, int a[*]);   // Only allowed in function prototypes. 
void f(int i, int a[static i]); 

Kể từ khi thông số chức năng mảng chỉ đơn giản là phân rã để con trỏ, là có bất kỳ sự khác biệt thực tế nào giữa các tuyên bố trước đó, hay nó là vấn đề về phong cách? Khi nào thì sử dụng chúng? Cụ thể, loại vòng loại static ngụ ý là gì? Tiêu chuẩn không hiển thị rõ ràng lý do cho mỗi cú pháp.

Trả lời

23

Miễn là bạn đang làm việc với các mảng một chiều, các khai báo trên đều tương đương nhau. Người cuối cùng mặc dù

void f(int i, int a[static i]) 

có tác dụng phụ. Nó tương đương với các kiểu trước đó về kiểu tham số, nhưng cũng cho trình biên dịch biết rằng nó có thể dựa vào tham số a trỏ tới một mảng có ít nhất i yếu tố (có thể được sử dụng trong tối ưu hóa).

Bạn cũng đang quên một tuyên bố mới

void f(int i, int a[const]) 

Cái này thực sự không có một tác dụng ngay cả trong trường hợp của một mảng đơn chiều. Nó tương đương với

void f(int i, int *const a) 

mặc dù một số người có thể cho rằng const-qualifications về tham số chức năng là vô ích. Trước khi nó không thể const-đủ điều kiện con trỏ tham số mảng "phân rã" khi sử dụng cú pháp [] cho việc khai báo.

Các * (cũng như i) giữa [] bắt đầu có vấn đề duy nhất khi nó được sử dụng giữa các cặp thứ hai (hoặc cao hơn) của [] trong khai báo mảng đa chiều. Về bản chất, nó cũng giống như nó luôn luôn là: kích thước mảng trong khai báo tham số luôn chỉ quan trọng giữa cặp thứ hai hoặc tiếp theo là []. * được sử dụng trong các khai báo mẫu cho các tham số VLA, khi giá trị kích thước không được đặt tên rõ ràng. Ví dụ: bạn có thể khai báo

void bar(int n, int m, int a[n][m]); 

và trình biên dịch sẽ biết rằng a là VLA vì kích thước không phải là hằng số. Nhưng nếu bạn không muốn đặt tên cho các tham số trong nguyên mẫu, làm thế nào bạn sẽ nói với trình biên dịch rằng a là một VLA? Đó là khi * giúp

void bar(int, int, int a[*][*]); 
+2

Cảm ơn bạn đã làm rõ. Ban đầu tôi nghi ngờ rằng vòng loại 'tĩnh' có liên quan đến các vấn đề tối ưu hóa. Ngoài ra, bạn quên đề cập đến bất kỳ loại vòng loại nào có thể được khai báo trong khai báo mảng và chúng có thể đóng vai trò quan trọng (chẳng hạn như 'limits' hoặc' volatile') so với 'const'. – alecov

+0

Nếu tôi thực hiện 'func (int a [static 4] [6])' thì static chỉ có thể được khai báo trong các dấu ngoặc đầu tiên. Nếu tôi làm điều này 'func (int (* a) [tĩnh 6]) 'điều này sẽ làm gì? Cho phép tôi tìm nạp trước 6 giá trị đầu tiên của hàng đầu tiên? Và cuối cùng những gì về 'func (int * a [static 6])'? – user10607

+0

Điều gì sẽ là ý nghĩa của 'void func1 (int a [-1])', 'void func2 (int a [some_global ++]);', hoặc 'void func3 (int length, int dat [length]);'? – supercat