В режиме строгого соответствия (что означает «в теории») вы вызываете неопределенное поведение (что плохо), когда вы вызываете функцию, которая принимает переменное число аргументов без объявления прототипа функции в области видимости. Это означает, что компилятору разрешено делать все, что ему нравится, с программой, которая использует printf()
без прототипа из #include <stdio.h>
или эквивалентного объявления. «Все что угодно» включает в себя правильную работу в качестве одного из вариантов; похоже, это вариант, выбранный вашим примером.
На практике код будет работать нормально с большинством практических компиляторов даже без формального объявления функции printf()
.
Как указывал qrdl, функция была найдена, потому что компилятор C связывается с библиотекой C.
Обратите внимание, что комментарий Криса Янга о C99 и 'implicit int' точен, но правило о том, что 'функции переменных аргументов должны иметь прототип в области видимости', применимо как к C89, так и к C99. Большинство компиляторов не работают в строгом режиме совместимости с C99 по умолчанию, потому что слишком много кода, который не скомпилируется таким образом.
Крис Янг прокомментировал:
Для пояснения, мой комментарий был о том, что C99 удаляет неявные объявления. Говоря «implicit int», я думаю, что вы имеете в виду функцию C89, разрешающую такие объявления, как foo (void); означать int foo (void); что-то C99 также удалено.
Крис, конечно, прав. Было две функции «неявного объявления», удаленные из стандарта C99. В предисловии к стандарту перечисляются их:
- удалить неявное
int
- удалить неявное объявление функции
Я не думал (и, следовательно, не писал) достаточно ясно. Тем не менее, и C89, и C99 требуют прототипа для функций, которые принимают переменное число аргументов.
Для иллюстрации:
extern int pqr();
int main(void)
{
int i = pqr(1, 3);
return i;
}
Без первой строки это правильный фрагмент C89 с неявным объявлением функции pqr()
в качестве функции, которая возвращает целое число (с неопределенными аргументами). Если первая строка заменена на extern pqr();
, то это правильный фрагмент C89 с явным объявлением pqr()
в качестве функции, которая возвращает целое число (с неопределенными аргументами), но тип возвращаемого значения - «неявный int
» , Как написано, функция объявлена явно и имеет явный тип возврата int
, но у нее все еще есть неопределенные аргументы. Я считаю, что это действительно C99 - хотя и не совсем желательно. Конечно, GCC (3.4.4) принимает его с опциями «-std=c99 -pedantic
». В идеале, объявление функции должно включать полный прототип. (И, если pqr()
были определены с помощью многоточия, этот прототип потребовался бы в теории !)