Есть ли разница между foo (void) и foo () в C ++ или C?


Ответы:


317

В С :

  • void foo()означает «функция, fooпринимающая неопределенное количество аргументов неопределенного типа»
  • void foo(void)означает «функция foo, не имеющая аргументов»

В C ++ :

  • void foo()означает «функция foo, не имеющая аргументов»
  • void foo(void)означает «функция foo, не имеющая аргументов»

Таким образом, при написании foo(void)мы получаем одинаковую интерпретацию для обоих языков и делаем наши заголовки многоязычными (хотя нам обычно нужно сделать что-то еще с заголовками, чтобы сделать их действительно мультиязычными, а именно, обернуть их в extern "C"компиляцию, если мы собираем C ++).


10
Но если бы C ++ потребовал void, то он мог бы избежать проблемы «самого неприятного анализа».
Адриан Маккарти

5
Да, но в C ++ есть много других паршивых разборов, и нет смысла в этом говорить.
DrPizza

16
На недавнем вопросе @James Kanze опубликовал интересную новость. Перепишите здесь, чтобы не потерять его: первые версии C не позволяли указывать количество параметров, которые может принимать функция, поэтому void foo()был единственным синтаксисом для объявления функции. Когда подписи были введены, комитет C должен был устранить неоднозначность со старым синтаксисом и ввести void foo(void)синтаксис. С ++ взял это ради совместимости.
Матье М.

3
Можете ли вы привести пример C C90 и более поздних версий, где использование void foo()вместо void foo(void)даст функциональную разницу? Т.е. я уже много лет пользуюсь версией без пустоты и не вижу никаких проблем, я что-то упустил?
chacham15

6
@ chacham15 void foo() { if ( rand() ) foo(5); } компилируется и запускается (вызывая неопределенное поведение, если вам не очень везет), тогда как void foo(void)с таким же телом может произойти ошибка компиляции.
ММ

39

Я понимаю, что ваш вопрос относится к C ++, но когда дело доходит до C, ответ можно найти в K & R, стр. 72-73:

Кроме того, если объявление функции не включает аргументы, как в

double atof();

это также означает, что в аргументах atof ничего не следует предполагать; проверка всех параметров отключена. Это специальное значение пустого списка аргументов предназначено для того, чтобы старые программы на С могли компилироваться с новыми компиляторами. Но это плохая идея использовать его с новыми программами. Если функция принимает аргументы, объявите их; если это не требует аргументов, используйте void.


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

9

C ++ 11 N3337 стандартная версия

Нет никакой разницы.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

Приложение C "Совместимость" C.1.7 Пункт 8: заявители говорят:

8.3.5 Изменение: в C ++ функция, объявленная с пустым списком параметров, не принимает аргументов. В C пустой список параметров означает, что число и тип аргументов функции неизвестны.

Пример:

int f();
// means int f(void) in C ++
// int f( unknown ) in C

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

Влияние на исходную функцию: изменение семантики четко определенной функции. Эта функция была помечена как «устаревшая» в C.

8.5.3 функции говорит:

4. Параметр-объявление-предложение определяет аргументы, которые можно указать, и их обработку при вызове функции. [...] Если параметр-объявление-предложение пуст, функция не принимает аргументов. Список параметров (void) эквивалентен пустому списку параметров.

C99

Как упоминалось в C ++ 11, int f()ничего не указывает на аргументы и является устаревшим.

Это может привести либо к рабочему коду, либо к UB.

Я подробно интерпретировал стандарт C99 по адресу: https://stackoverflow.com/a/36292431/895245


2

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


1
«прототип» означает объявление списка аргументов и тип возвращаемого значения. Я говорю это потому, что «прототип» сбил меня с толку относительно того, что вы имели в виду вначале.
Zan Lynx
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.