В чем разница между функцией () и функцией (void)?

28

Я слышал, что хорошей практикой является написание функций, которые не получают ничего в качестве параметра, подобного этому:

int func(void);

Но я слышал, что правильный способ выразить это так:

int func();

В чем разница между этими двумя объявлениями функций в C и C ++?

Гризли
источник
5
Это дубликат тысячи других вопросов в сети сайта, среди прочего stackoverflow.com/questions/18167390/…
Ларс Виклунд
@LarsViklund это только дубликат, если есть вопрос на этом сайте. Я не могу найти один, поэтому независимо от того, что находится на SO, это не дубликат. Вероятно, стоит оставить этот вопрос в качестве указателя, если ничего больше.
1
@LightnessRacesinOrbit мы обсуждали в чате и решили оставить его с некоторыми изменениями.
stackoverflow.com/questions/693788/… | stackoverflow.com/questions/51032/… | stackoverflow.com/questions/416345/…
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件

Ответы:

17

C и C ++ отличаются в этом отношении.

C 2011 Онлайн Стандарт

6.7.6.3 Деклараторы функций (включая прототипы)
...
10 Особый случай безымянного параметра типа voidв качестве единственного элемента в списке указывает на то, что функция не имеет параметров.
...
14 Список идентификаторов объявляет только идентификаторы параметров функции. Пустой список в деклараторе функции, который является частью определения этой функции, указывает на то, что функция не имеет параметров. Пустой список в объявителе функции, который не является частью определения этой функции, указывает на то, что информация о количестве или типах параметров не предоставляется. 145)

Короче говоря, пустой список параметров в функции декларации указывает , что функция принимает неопределенное количество параметров, в то время как пустой список параметров в функции определения указывает , что функция не принимает ни одного параметра.

T foo( void ); // declaration, foo takes no parameters
T bar();       // declaration, bar takes an *unspecified* number of parameters

T foo( void ) { ... } // definition, foo takes no parameters
T bar() { ... }       // definition, bar takes no parameters

Что касается C, вы никогда не должны использовать пустой список идентификаторов в объявлении или определении функции. Если функция не предназначена для принятия каких-либо параметров, укажите это с помощью voidсписка параметров.

Онлайн стандарт C ++

8.3.5 Функции [dcl.fct]
...
4 Параметр-объявление-предложение определяет аргументы, которые могут быть указаны, и их обработку при вызове функции. [ Примечание: параметр декларирование придаточного используется для преобразования аргументов , указанных в вызове функции; см. 5.2.2. - примечание конца ] Если предложение -объявление-предложение пусто, функция не принимает аргументов. Список параметров, состоящий из одного безымянного параметра независимого типа void, эквивалентен пустому списку параметров. За исключением этого особого случая, параметр не должен иметь тип cv void. Если параметр-объявление-предложениезаканчивается многоточием или пакетом параметров функции (14.5.3), число аргументов должно быть равно или больше количества параметров, которые не имеют аргумента по умолчанию и не являются пакетами параметров функции. Там, где синтаксически правильно и где «...» не является частью абстрактного декларатора , «, ...» является синонимом «...». [ Пример: объявление
    int printf(const char*, ...);
объявляет функцию, которая может быть вызвана с различными номерами и типами аргументов.
    printf("hello world");
    printf("a=%d b=%d", a, b);
Тем не менее, первый аргумент должен быть такого типа , который может быть преобразован в const char*- конец примера ] [ Примечание: Стандартный заголовок <cstdarg>содержит механизм для доступа аргументов , передаваемых с помощью многоточие (см 5.2.2 и 18.10). - конец примечания ]

В случае C ++ пустой список параметров в объявлении или определении указывает, что функция не принимает аргументов и эквивалентна использованию списка параметров void.

Джон Боде
источник
35

В C функция с пустым списком параметров ()может принимать все что угодно для своих аргументов. Буквально что угодно. Это обычно используется для реализации функции, которая может принимать переменное число аргументов , хотя в наши дни считается предпочтительным использовать более явный синтаксис многоточия (...)для этих функций.

В C функция со списком параметров (void)явно не принимает ничего для своих аргументов. Это означает, что компилятор может фактически сказать вам, что вы допустили ошибку, если попытаетесь что-то передать.

В C ++ эти объявления функций эквивалентны. Пустой список параметров означает «нет параметров» так же, как voidи.

Ixrec
источник
Re: «Это обычно используется для реализации функции, которая может принимать переменное число аргументов»: Вы уверены в этом? Я не думаю, что когда-либо видел программу, которая использовала явные списки параметров для предварительных объявлений невариантных функций и ()для функций с переменным числом. У вас есть пример программы, которая использует это соглашение?
Руах
4
Функция переменного переменного тока должна быть определена с помощью ...синтаксиса, и она должна иметь хотя бы один именованный параметр. Определение такой функции ()приводит к неопределенному поведению - и у тела функции нет возможности использовать макросы, определенные в, <stdarg.h>для чтения значений параметров. Это имело место со стандарта 1989/1990 гг.
Кит Томпсон
@KeithThompson: Этот вопрос и этот ответ говорят о предварительных декларациях, а не об определениях функций.
Руах
3
@ruakh: функция variadic должна быть объявлена и определена с использованием ...синтаксиса, чтобы избежать неопределенного поведения.
Кит Томпсон