2010-06-22 5 views
34

Sự khác nhau giữa khai báo hàm K & R và khai báo hàm ANSI là gì?Khai báo hàm: K & R so với ANSI

+1

Bạn có thể đưa ra ví dụ về mỗi kiểu không? –

+2

Câu hỏi liên quan: http://stackoverflow.com/questions/1630631/what-is-useful-about-this-c-syntax – sharptooth

+1

Đó là "K & R", chứ không phải "knr" (Tôi đã sửa câu hỏi cho bạn) , viết tắt của Kernighan và Ritchie và thường đề cập đến cú pháp C được mô tả trong cuốn sách chủ đề của họ trên C circa 1978, * Ngôn ngữ lập trình C *. Bài viết này có thể hữu ích cho bạn: http://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C –

Trả lời

54

K & Cú pháp R đã lỗi thời, bạn có thể bỏ qua nó trừ khi bạn phải duy trì mã cũ.

// K&R syntax 
int foo(a, p) 
    int a; 
    char *p; 
{ 
    return 0; 
} 

// ANSI syntax 
int foo(int a, char *p) 
{ 
    return 0; 
} 
+13

Sử dụng cú pháp K & R với loại 'void *' là một lỗi thời, vì K & R C không * có * 'void *'. – caf

+3

@caf Không, tôi đang sử dụng phần mở rộng không chuẩn cho ngôn ngữ :-) – Wizard

+3

Thực ra, đây là định nghĩa hàm K & R, không phải là khai báo hàm K & R. –

19

Legacy K khai báo/Định nghĩa &-Style R

Khi Kernighan và Ritchie xuất bản lần đầu "The C Programming Language", C vẫn chưa cung cấp đầy đủ các nguyên mẫu hàm. Chuyển tiếp các khai báo các hàm đã tồn tại, nhưng với mục đích duy nhất là chỉ ra một kiểu trả về. Đối với các hàm trả về int, chúng không bắt buộc cho đến C99.

Bởi C89, khái niệm về nguyên mẫu hàm, cũng xác định loại tham số (và, ngầm định là số của chúng) đã được thêm vào. Vì nguyên mẫu cũng là một kiểu khai báo chức năng, thuật ngữ không chính thức "K & Khai báo chức năng R" đôi khi được sử dụng cho một khai báo hàm không phải là một mẫu thử nghiệm.

// K&R declarations, we don't know whether these functions have parameters. 
int foo(); // this declaration not strictly necessary until C99, because it returns int 
float bar(); 

// Full prototypes, specifying the number and types of parameters 
int foo(int); 
float bar(int, float); 

// K&R definition of a function 
int foo(a) 
    int a; // parameter types were declared separately 
{ 
    // ... 
    return 0; 
} 

// Modern definition of a function 
float bar(int a, float b) 
{ 
    // ... 
    return 0.0; 
} 

Tuyên bố R tình cờ K &

Nó đáng chú ý là những người mới đến C có thể vô tình sử dụng K & tờ khai R khi họ có ý định sử dụng một nguyên mẫu đầy đủ, bởi vì họ có thể không nhận ra rằng một sản phẩm nào danh sách tham số phải được chỉ định là void.

Nếu bạn khai báo và định nghĩa một hàm như

// Accidental K&R declaration 
int baz(); // May be called with any possible set of parameters 

// Definition 
int baz() // No actual parameters means undefined behavior if called with parameters. 
      // Missing "void" in the parameter list of a definition is undesirable but not 
      // strictly an error, no parameters in a definition does mean no parameters; 
      // still, it's better to be in the habit of consistently using "void" for empty 
      // parameter lists in C, so we don't forget when writing prototypes. 
{ 
    // ... 
    return 0; 
} 

... sau đó bạn chưa thực sự được đưa ra một nguyên mẫu cho một hàm mang theo không có tham số, nhưng một tuyên bố trong K & R-phong cách cho một hàm chấp nhận một số lượng không xác định các tham số của loại không xác định.

Ghi chú AnT trong this answer đối với câu hỏi tương tự mà cú pháp này không được dùng nhưng vẫn hợp pháp như C99 (và hàm trỏ đến chức năng với số và loại tham số không xác định vẫn có ứng dụng tiềm năng, mặc dù có nguy cơ cao về hành vi không xác định) ; như vậy, các trình biên dịch tuân thủ sẽ tốt nhất, tạo ra một cảnh báo nếu một hàm được khai báo hoặc được gọi mà không có một nguyên mẫu thích hợp.

Chức năng gọi không có mẫu thử ít an toàn hơn, vì trình biên dịch không thể xác minh rằng bạn đã chuyển đúng số lượng và loại tham số theo đúng thứ tự; kết quả hành vi không xác định nếu cuộc gọi không thực sự chính xác.

Cách đúng để khai báo và định nghĩa một hàm parameterless là, tất nhiên:

// Modern declaration of a parameterless function. 
int qux(void); // "void" as a parameter type means there are no parameters. 
       // Without using "void", this would be a K&R declaration. 

// Modern definition of a parameterless function 
int qux(void) 
{ 
    // ... 
    return 0; 
} 
+1

Bạn cần phải làm rõ ý nghĩa của các 'phiên bản cũ hơn của C'. Bạn nói: Các phiên bản _Older của ngôn ngữ C không yêu cầu các nguyên mẫu hàm đầy đủ, nhưng vẫn yêu cầu khai báo trước một hàm trước khi nó có thể được gọi._ Nhưng các phiên bản cũ hơn của C, có nghĩa là chuẩn C, không có nguyên mẫu ở tất cả và không yêu cầu tuyên bố trước của một hàm trước khi nó có thể được gọi. Ngay cả C89/C90 cũng không yêu cầu những tờ khai chuyển tiếp như vậy. Đó là C99 yêu cầu khai báo các hàm (nhưng vẫn không bắt buộc nguyên mẫu) trước khi sử dụng. –

+0

@ JonathanLeffler Cảm ơn những lời khuyên, tôi đã đọc thêm một chút (chủ yếu là bài viết Wikipedia về K & R thời đại C) và làm sạch nó lên, tôi nghĩ rằng nó nên được lịch sử chính xác bây giờ. –

0

Tôi chỉ muốn nói thêm rằng trong K & phong cách R bổ kiểu truyền thống cho các chức năng mà trả về một giá trị int aren' t thậm chí cần thiết.

Cân nhắc các ký hiệu C11 hiện đại của một chương trình HelloWorld đơn giản:

int main(int argc, char **argv) { 
    printf("hello world\n"); 
    return 0; 
} 

này tương đương với K & R ký hiệu phong cách:

main(argc, argv) 
int argc; 
char **argv; 
{ 
printf("hello world\n"); 
return 0; 
} 

Lưu ý rằng int trước main() được bỏ qua, nhưng mã vẫn biên dịch. Đó là một phần của định nghĩa K & R.

Trích Wikipedia:

Trong các phiên bản đầu tiên của C, chỉ có chức năng đó quay trở lại một giá trị không phải là int cần phải được tuyên bố nếu được sử dụng trước khi định nghĩa hàm; một hàm được sử dụng mà không có bất kỳ khai báo trước nào được giả định trả về kiểu int, nếu giá trị của nó được sử dụng.

--source: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C

này được cho là một di sản mã hóa theo phong cách và nên tránh do các vấn đề rõ ràng, nhưng khá thường xuyên giáo trình thuật toán cũ ủng hộ loại này của K & phong cách R.

+2

Và đối với masochistic, bạn có thể có 'main (argc, argv) char ** argv; {…} 'Như kiểu của các đối số không có một đặc tả kiểu rõ ràng là, bằng suy luận,' int'. Ngoài ra, 'hàm (a, b, c, d) char * d, gấp đôi c, a; {…} 'Cũng ổn; các tên không phải được liệt kê trong phần loại theo thứ tự xuất hiện trong danh sách đối số. –