Почему функции без определенных аргументов можно вызывать с любым количеством аргументов?
В C, если функция определена с 0 аргументами (пустой список параметров), вызывается с любым количеством аргументов, gcc не выдает никакой ошибки. Почему это так?
3 ответа
TL; DR - int func(void) {..
а также int func() {..
не то же самое.
В первом случае путем явного упоминания
void
в качестве типа параметра (идентификатор не требуется) обратите внимание, что функция определена как таковая, поэтому входного параметра нет, поэтому при вызове он не должен передавать никаких аргументов.В последнем случае не выполняется проверка количества передаваемых аргументов, поэтому вам разрешено передавать любое количество и тип аргументов.
Замечания:
Согласно C11
Глава §6.9.1
Если декларатор включает список типов параметров, объявление каждого параметра должно включать идентификатор, за исключением особого случая списка параметров, состоящего из одного параметра типа
void
, в этом случае не должно быть идентификатора. Список объявлений не должен следовать.
Потому что так C-спецификации определяют функцию.
Если вы хотите, чтобы функция не принимала аргументов, явно укажите void
в списке аргументов.
Если вы хотите, чтобы функция принимала переменное число аргументов, используйте переменные аргументы ...
, Или в древнем C вы можете оставить список аргументов пустым, и компилятор будет применять продвижение по умолчанию для каждого аргумента.
Хотя последнее сейчас устарело: из раздела 6.11.6 Деклараторы функций C11 spec n1570 draft
Использование деклараторов функций с пустыми скобками (не деклараторы типа параметров в формате prototype) является устаревшей функцией.
Рассмотрим этот кусок кода:
//void Test(int a);
int main()
{
int a = 0;
Test();
return 0;
}
Он будет компилироваться (в основном с предупреждением в зависимости от компилятора, настроек и т. Д.), Потому что компилятор предполагает, что Test
это функция, принимающая любое количество аргументов и возвращающая int
, Это также называется "неявное объявление". Вы никогда не должны использовать эту устаревшую функцию языка C.
Если вы раскомментируете первую строку void Test(int a);
, он больше не будет компилироваться, потому что теперь компилятор знает, что Test
это функция, возвращающая int
и взять ровно один int
аргумент и как мы называем Test()
без аргументов компилятор может выдать ошибку, потому что аргументы при вызове не совпадают с аргументами функции, когда она была объявлена.
Теперь мы можем задать вопрос: почему неявное объявление разрешено в первую очередь? Ну, это так, как язык был разработан. ИМО это ошибка дизайна.