является ли f (void) устаревшим в современных C и C ++ [дубликат]

StackOverflow https://stackoverflow.com/questions/416345

  •  03-07-2019
  •  | 
  •  

Вопрос

В настоящее время я занимаюсь рефакторингом / приведением в порядок некоторого старого кода C, используемого в проекте C ++, и регулярно вижу такие функции, как:

int f(void)

который я бы, как правило, написал как:

int f()

Есть ли какая-либо причина не заменять (void) на () по всей кодовой базе, чтобы улучшить согласованность, или есть тонкая разница между ними, о которой я не знаю?Более конкретно, если виртуальная функция-член в C ++ описывается как:

virtual int f(void)

и производный класс включает в себя функцию-член:

int f()

является ли это допустимым переопределением?Кроме того, могу ли я столкнуться с какими-либо проблемами компоновщика, основанными на почти идентичных сигнатурах?

Это было полезно?

Решение

В C декларация int f(void) означает функцию, возвращающую значение int, которое не принимает параметров.Декларация int f() означает функцию, возвращающую значение int, которое принимает любое количество параметров.Таким образом, если у вас есть функция, которая не принимает параметров на C, первая является правильным прототипом.

В C ++, я полагаю int f(void) является устаревшим, и int f() является предпочтительным, поскольку это конкретно означает функцию, которая не принимает параметров.

Другие советы

Чтобы добавить к ответу Криса, используя int f() по моему опыту, это плохая практика в C, поскольку вы теряете способность компилятора сравнивать объявление функции с ее определением, чтобы гарантировать, что она будет вызвана правильно.

Например, следующий код соответствует стандартам C:

#include <stdio.h>
void foo();
void bar(void) {
    foo();
}
void foo(int a) {
    printf("%d\n", a);
}

Но это приводит к неопределенному поведению, поскольку a не был передан в foo.

В C ++ существует две версии foo:тот, который не принимает аргументов, и тот, который принимает int.Итак bar завершается вызовом неопределенной версии, что приведет к ошибке компоновщика (при условии, что нет других определений foo где угодно).

Приведенные выше ответы вполне верны, но я ссылаюсь на превосходную страницу Дэвида Триббла, поскольку она дает отличное объяснение по этому и многим другим вопросам.

Основные моменты:

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

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

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

Прототипы пустых функций являются устаревшей функцией в C99 (как они были в C89).

Редактировать:Ознакомившись со стандартом, возможно, стоит отметить, что синтаксис func (void) является не устарел в C ++, но обычно считается скорее идиомой в стиле C.Я думаю, что большинство программистов на C ++, с которыми я сталкивался, предпочитают пустой список параметров.

Правка 2:Добавление цитаты из стандарта C ++, раздел 8.3.5, параграф 2:

"Если параметр-declaration-clause пуст, функция не принимает аргументов.Список параметров (void) эквивалентен пустому списку параметров.За исключением этого особого случая, void не должен быть типом параметра (хотя типы, производные от void, такие как void*, могут)."

Там нет упоминания о том, что любая из форм устарела.Еще раз спасибо мистеруОтличный веб-сайт Tribble, который указал мне на правильный раздел стандарта.

tl; dr:использование void.

Учитывая обратную совместимость в C ++ и некоторую двусмысленность, указанную ниже, я утверждаю, что мы полностью возвращаемся к KnR и ANSI C для получения окончательного ответа:

int getline(void);
int copy(void)

Поскольку специализированные версии getline и copy не имеют аргументов, логика подсказывает, что их прототипы в начале файла должны быть getline() и copy().Но для совместимости с более старыми программами на C стандарт принимает пустой список в качестве объявления старого стиля и отключает проверку списка всех аргументов;это слово void должен использоваться для явно пустого списка.[Керниган и Ричи, язык программирования Си, 1988, страницы 32-33]

и..

Особое значение пустого списка аргументов предназначено для того, чтобы разрешить старые программы на C компилироваться с новыми компиляторами.Но это плохая идея использовать его с новыми программами.Если функция принимает аргументы, объявите их;если он не принимает аргументов, используйте void [там же, стр.73]

Редактировать:Остальное вынесите на отдельное обсуждение здесь:Обращается ли указание на использование void в объявлении функции, которая не принимает аргументов, к Самому неприятному синтаксическому анализу?

Стандартная осадка C11 N1570

void f() является устаревшим, void f(void) Рекомендуемые:

6.11.6 Описатели функций:

1 Использование деклараторов функций с пустыми круглыми скобками (не параметр формата прототипа деклараторы типов) является устаревшей функцией.

Введение:

2 Некоторые функции устарели, что означает, что их можно рассмотреть на предмет исключения в будущих версиях этого международного стандарта.Они сохранены из-за их широкого использования, но их использование в новых реализациях (для реализации функций) или новых программах (для языка [6.11] или библиотечных функций [7.31]) не рекомендуется.

Подробное обсуждение: https://stackoverflow.com/a/36292431/895245

Проект стандарта C ++ 11 N3337

Ни то , ни другое void f(void) ни void f() являются устаревшими.

void f(void) существует для совместимости с C. Приложение C "Совместимость" C.1.7 Пункт 8:декларанты:

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

С тех пор как void f() устарел в C и void f(void) Рекомендуемые, void f(void) будет существовать до тех пор, пока C ++ хочет поддерживать совместимость.

void f(void) и void f() то же самое и в C ++.Так что чем дольше void f(void) имеет смысл только в том случае, если вы заботитесь о написании кода, который компилируется как на C, так и на C ++, что, скорее всего, не стоит того.

Подробное обсуждение: https://stackoverflow.com/a/36835303/895245

В C++, int f(void) действительно, это устаревшее объявление, которое на 100% эквивалентно int f().IT является та же подпись.В void в этом контексте столь же важно, как, например,пробел.Это также означает, что на них распространяется правило единого определения (они не перегружают) и Derived::f(void) переопределяет Base::f().

Не связывайся с такими вещами, как f(const void), хотя.Нет единого мнения о том, что означает такого рода странность.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top