Чим відрізняється функція () від функції (void)?


27

Я чув, що є гарною практикою писати функції, які не отримують нічого в якості такого параметра:

int func(void);

Але я чую, що правильний спосіб виразити це так:

int func();

Яка різниця між цими двома деклараціями функцій як у C, так і в C ++?


5
Це дублікат тисячі інших питань у мережі сайту, серед інших stackoverflow.com/questions/18167390/…
Ларс Віклунд,

@LarsViklund це лише дублікат, якщо є питання на цьому сайті. Я не можу його знайти, тому незалежно від того, що є на SO, це не дублікат. Напевно, варто тримати це питання навколо як покажчика, якщо нічого іншого.


1
@LightnessRacesinOrbit ми обговорили в чаті і вирішили зберегти його з деякими правками.

Відповіді:


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і.


Re: "Зазвичай це використовується для реалізації функції, яка може приймати змінну кількість аргументів": Ви впевнені в цьому? Я не думаю, що я ніколи не бачив програми, яка використовувала явні списки параметрів для переадресації оголошень не варіантних функцій і ()для варіантів. Чи є у вас приклад програми, яка використовує цю конвенцію?
ruakh

4
Змінна функція змінного струму повинна бути визначена ...синтаксисом, і вона повинна мати принаймні один названий параметр. Визначення такої функції ()викликає невизначену поведінку - і тіло функції не може використовувати макроси, визначені в <stdarg.h>для читання значень параметрів. Це стосується стандарту 1989/1990 років.
Кіт Томпсон

@KeithThompson: Це питання та ця відповідь говорять про попередні визначення, а не про визначення функцій.
ruakh

3
@ruakh: Варіантну функцію необхідно оголосити та визначити за допомогою ...синтаксису, щоб уникнути невизначеної поведінки.
Кіт Томпсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.