Trong chế độ tuân thủ nghiêm ngặt (có nghĩa là "theo lý thuyết"), bạn gọi hành vi không xác định (điều này không tốt) khi bạn gọi hàm có số lượng đối số thay đổi mà không có khai báo mẫu của hàm trong phạm vi. Điều đó có nghĩa rằng trình biên dịch được phép làm bất cứ điều gì nó thích với một chương trình sử dụng printf()
mà không có nguyên mẫu từ #include <stdio.h>
hoặc khai báo tương đương. "Bất cứ điều gì nó thích" bao gồm hoạt động chính xác như một trong các tùy chọn; dường như là tùy chọn được chọn bởi ví dụ của bạn.
Trong thực tế, mã sẽ hoạt động OK với hầu hết các trình biên dịch thực tế ngay cả khi không khai báo chính thức chức năng printf()
.
Như đã được chỉ ra bởi qrdl, hàm được tìm thấy vì trình biên dịch C liên kết với thư viện C.
Lưu ý rằng nhận xét của Chris Young về C99 và 'int ngầm' là chính xác, nhưng quy tắc về 'hàm đối số biến phải có mẫu thử trong phạm vi' áp dụng cho cả C89 và C99. Hầu hết các trình biên dịch không hoạt động trong chế độ tương thích C99 nghiêm ngặt theo mặc định vì có quá nhiều mã sẽ không biên dịch như vậy.
Chris Young nhận xét:
Để làm rõ, nhận xét của tôi là trên C99 loại bỏ tờ khai ngầm. Bằng cách nói "int ngầm", tôi nghĩ bạn đang đề cập đến tính năng C89 cho phép khai báo như foo (void); có nghĩa là int foo (void) ;, một cái gì đó C99 cũng bị loại bỏ.
Chris đương nhiên là đúng. Có hai tính năng 'khai báo ngầm' bị loại bỏ khỏi tiêu chuẩn C99.Lời nói đầu của tiêu chuẩn liệt kê chúng như:
- loại bỏ ngầm
int
- loại bỏ khai báo hàm ẩn
tôi đã không suy nghĩ (và do đó không viết) rõ ràng đủ. Tuy nhiên, cả C89 và C99 đều yêu cầu một nguyên mẫu trong phạm vi cho các hàm có số lượng đối số thay đổi.
Để minh họa:
extern int pqr();
int main(void)
{
int i = pqr(1, 3);
return i;
}
Nếu không có dòng đầu tiên, đây là một mảnh C89 đúng với khai báo ngầm của hàm pqr()
như một hàm trả về một số nguyên (với các đối số không xác định). Nếu dòng đầu tiên được thay thế bằng extern pqr();
, thì đây là đoạn C89 đúng với khai báo rõ ràng là pqr()
làm hàm trả về một số nguyên (với đối số không xác định), nhưng kiểu trả về là 'ngụ ý int
'. Như được viết, hàm được khai báo rõ ràng và có loại trả về int
rõ ràng - nhưng nó vẫn có các đối số không xác định. Tôi tin rằng đó là hợp lệ C99 - mặc dù không hoàn toàn mong muốn. Chắc chắn, GCC (3.4.4) chấp nhận nó với các tùy chọn '-std=c99 -pedantic
'. Lý tưởng nhất, khai báo hàm phải bao gồm nguyên mẫu đầy đủ. (Và, nếu pqr()
được xác định bằng dấu ba chấm, nguyên mẫu đó sẽ được yêu cầu trong lý thuyết!)
Lưu ý rằng trong C89/C90, bạn nên cung cấp một giá trị trả về từ 'main()' .C99 cho phép bạn bỏ qua 'return 0;' hoặc tương đương từ cuối 'main()' –