Cú pháp C thay thế (K&R) cho khai báo hàm so với nguyên mẫu


76

Điều gì hữu ích về Ccú pháp này - sử dụng khai báo hàm kiểu 'K&R'?

Tôi đã có thể viết điều này trong Visual Studios 2010beta

Tôi không hiểu. Điểm của cú pháp này là gì? Tôi có thể viết:

Điều duy nhất mà nó có vẻ chỉ định là nó sử dụng bao nhiêu tham số và kiểu trả về. Tôi đoán các tham số không có kiểu thì khá tuyệt, nhưng tại sao lại cho phép nó và int paranNamesau bộ khai báo hàm? Thật kỳ lạ.

Ngoài ra đây vẫn là tiêu chuẩn C?


Đó là một kiểu khai báo hàm cũ hơn. Vui lòng xem liên kết này. /programming/22500/what-are-the-major-differences-between-ansi-c-and-kr-c link text
Leonidas Tsampros 27/10/09

Câu trả lời:


154

Câu hỏi bạn đang hỏi thực sự là hai câu hỏi, không phải một. Hầu hết các câu trả lời cho đến nay đều cố gắng che toàn bộ nội dung bằng một tấm chăn chung chung "đây là kiểu K&R", trong khi trên thực tế, chỉ một phần nhỏ của nó có liên quan gì đến thứ được gọi là kiểu K&R (trừ khi bạn thấy toàn bộ ngôn ngữ C. là "K & R-style" theo cách này hay cách khác :)

Phần đầu tiên là cú pháp lạ được sử dụng trong định nghĩa hàm

Đây thực sự là một định nghĩa hàm kiểu K & R. Câu trả lời khác đã bao gồm điều này khá tốt. Và thực ra thì chẳng có gì nhiều. Cú pháp không được dùng nữa, nhưng vẫn được hỗ trợ đầy đủ ngay cả trong C99 (ngoại trừ quy tắc "không có int ngầm định" trong C99, nghĩa là trong C99, bạn không thể bỏ qua khai báo của p2).

Phần thứ hai ít liên quan đến phong cách K&R. Tôi đề cập đến thực tế là hàm có thể được gọi với các đối số "hoán đổi", tức là không có việc kiểm tra kiểu tham số nào diễn ra trong một lệnh gọi như vậy. Điều này rất ít liên quan đến định nghĩa kiểu K & R, nhưng nó liên quan đến mọi thứ liên quan đến chức năng của bạn không có nguyên mẫu. Bạn thấy đấy, trong C khi bạn khai báo một hàm như thế này

nó thực sự khai báo một hàm foonhận một số tham số không xác định của kiểu không xác định . Bạn có thể gọi nó là

và như

ans so (bạn có được ý tưởng);

Chỉ lệnh gọi với các đối số thích hợp mới "hoạt động" (nghĩa là các lệnh khác tạo ra hành vi không xác định), nhưng việc đảm bảo tính đúng đắn của nó là hoàn toàn tùy thuộc vào bạn. Trình biên dịch không bắt buộc phải chẩn đoán những cái không chính xác ngay cả khi bằng cách nào đó nó biết một cách kỳ diệu các loại tham số chính xác và tổng số của chúng.

Trên thực tế, hành vi này là một tính năng của ngôn ngữ C. Một điều nguy hiểm, nhưng vẫn là một tính năng. Nó cho phép bạn làm điều gì đó như thế này

tức là kết hợp các kiểu hàm khác nhau trong một mảng "đa hình" mà không có bất kỳ định dạng nào (mặc dù không thể sử dụng kiểu hàm đa dạng ở đây). Một lần nữa, sự nguy hiểm cố hữu của kỹ thuật này là khá rõ ràng (tôi không nhớ đã bao giờ sử dụng nó, nhưng tôi có thể tưởng tượng nó có thể hữu ích ở đâu), nhưng đó là C.

Cuối cùng, bit liên kết phần thứ hai của câu trả lời với phần đầu tiên. Khi bạn đưa ra định nghĩa hàm kiểu K & R, nó không giới thiệu một nguyên mẫu cho hàm. Đối với kiểu hàm có liên quan, funcđịnh nghĩa của bạn khai báo func

tức là cả kiểu và tổng số tham số đều không được khai báo. Trong bài đăng ban đầu của bạn, bạn nói "... nó có vẻ chỉ định là nó sử dụng bao nhiêu tham số ...". Chính thức mà nói, nó không! Sau khi funcxác định kiểu K & R hai tham số, bạn vẫn có thể gọifunc

và sẽ không có bất kỳ vi phạm ràng buộc nào trong đó. (Thông thường, một trình biên dịch chất lượng sẽ đưa ra cảnh báo cho bạn).

Ngoài ra, một thực tế đôi khi bị bỏ qua là

cũng là một định nghĩa chức năng kiểu K&R không giới thiệu nguyên mẫu. Để làm cho nó "hiện đại", bạn phải đặt một cách rõ ràng voidtrong danh sách tham số

Cuối cùng, trái với quan niệm phổ biến, cả định nghĩa hàm kiểu K & R và khai báo hàm không nguyên mẫu đều được hỗ trợ đầy đủ trong C99. Cái cũ đã không còn được dùng nữa kể từ C89 / 90, nếu tôi nhớ không lầm. C99 yêu cầu hàm phải được khai báo trước lần sử dụng đầu tiên, nhưng khai báo không bắt buộc phải là nguyên mẫu. Sự nhầm lẫn dường như bắt nguồn từ sự pha trộn thuật ngữ phổ biến: nhiều người gọi bất kỳ khai báo hàm nào là "nguyên mẫu", trong khi thực tế "khai báo hàm" không giống như "nguyên mẫu".


1
Nhưng sự khác biệt bây giờ giữa một hàm varargs và một hàm không được tạo mẫu.
Sebastian

1
@Sebastian Godelet kỳ đà không nghiêm ngặt. Ví dụ: gọi một hàm vararg với một int và bật nó dưới dạng byte là không hợp lệ. Việc xác định một hàm chỉ có các tham số vararg cũng vậy.
yyny

Các hàm @Sebastian Vararg thực sự có thể được gọi với nhiều tham số khác nhau một cách chính xác, chẳng hạn như printf. Các hàm không có nguyên mẫu chỉ có thể được gọi chính xác với một số đối số cố định nhất định, nhưng trình biên dịch không biết cái nào và không thể kiểm tra (vì vậy bạn phải làm điều đó).
not-a-user,

Tôi đoán đã đến lúc phải thay đổi supported even in C99. C99 to C11. :-).
sjsam

Tôi nhớ khi bắt đầu với C trên Amstrad PCW, tôi đã bối rối vì trình biên dịch sử dụng cú pháp khai báo hàm cũ đó nhưng cuốn sách hướng dẫn tôi có lại sử dụng cú pháp mới hơn. Đó là những ngày ... 25 năm trước ...!
Andrew Truckle

18

Đây là cú pháp K&R C khá cũ (trước ANSI / ISO C). Ngày nay, bạn không nên sử dụng nó nữa (vì bạn đã nhận thấy nhược điểm lớn của nó: trình biên dịch sẽ không kiểm tra các loại đối số cho bạn). Loại đối số thực sự được mặc định inttrong ví dụ của bạn.

Vào thời điểm đó, cú pháp này được sử dụng, đôi khi người ta sẽ tìm thấy các hàm như

mà thực sự là một định nghĩa có giá trị, như các loại cho foo, pqmặc định để int.


5

Đây chỉ đơn giản là một cú pháp cũ, có trước cú pháp "ANSI C" mà bạn có thể quen thuộc hơn. Nó thường được gọi là " K&R C ".

Các trình biên dịch hỗ trợ nó trở nên hoàn chỉnh và tất nhiên là có thể xử lý các cơ sở mã cũ.


2

Đó là một di tích từ khi C không có nguyên mẫu cho các chức năng. Hồi đó, (tôi nghĩ) các hàm được giả định là trả về intvà tất cả các đối số của nó được giả định là int. Không có kiểm tra nào được thực hiện trên các tham số chức năng.

Bạn tốt hơn nhiều nên sử dụng các nguyên mẫu hàm trong ngôn ngữ C hiện tại.
Và bạn phải sử dụng chúng trong C99 (C89 vẫn chấp nhận cú pháp cũ).

Và C99 yêu cầu các hàm phải được khai báo (có thể không có nguyên mẫu). Nếu bạn đang viết một hàm mới từ đầu, bạn cần phải cung cấp một khai báo ... hãy biến nó thành nguyên mẫu: bạn không mất gì và được kiểm tra thêm từ trình biên dịch.


4
Sai. Trong C99, các hàm phải được khai báo rõ ràng trước khi chúng được gọi. Tuy nhiên, C99 không yêu cầu một khai báo đã được gõ sẵn. C99 hỗ trợ đầy đủ cú pháp K&R với một thay đổi: intquy tắc ngầm định đã bị loại bỏ.
AnT

1

Đây là cú pháp K&R ban đầu trước khi C được chuẩn hóa vào năm 1989. C89 đã giới thiệu các nguyên mẫu hàm, mượn từ C ++ và không dùng cú pháp K&R. Không có lý do gì để sử dụng nó (và rất nhiều lý do để không) trong mã mới.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.