is f (void) deprecated in modern C and C++ [duplicate]

To pytanie ma już odpowiedź tutaj:

Obecnie refaktoryzuję / porządkuję stary kod C używany w projekcie C++ i regularnie widzę funkcje takie jak:

int f(void)

Które zwykle zapisywałbym jako:

int f()

Czy Jest jakiś powód, aby nie zastępować (void) przez () w kodzie w celu poprawy spójności, czy też jest subtelna różnica między tymi dwoma, których nie jestem świadomy? Bardziej szczegółowo, jeśli funkcja Wirtualnego członka w C++ jest opisana jako:

virtual int f(void)

I klasa pochodna zawiera funkcja członka:

int f()

Czy to poprawne obejście? Dodatkowo, czy prawdopodobnie napotkam jakieś problemy z linkerem oparte na prawie identycznych podpisach?

Author: Derek, 2009-01-06

6 answers

W C, deklaracja int f(void) oznacza funkcję zwracającą int, która nie przyjmuje żadnych parametrów. Deklaracja int f() oznacza funkcję zwracającą int, która przyjmuje dowolną liczbę parametrów. Tak więc, jeśli masz funkcję, która nie przyjmuje parametrów w C, pierwsza jest prawidłowym prototypem.

W C++ uważam, że int f(void) jest przestarzała, a int f() jest preferowana, ponieważ konkretnie oznacza funkcję, która nie przyjmuje parametrów.

 96
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-27 08:47:07

Aby dodać do odpowiedzi Chrisa, używanie int f() jest złą praktyką w C, z mojego doświadczenia, ponieważ tracisz zdolność kompilatora do porównywania deklaracji funkcji z jej definicją, aby upewnić się, że zostanie ona poprawnie wywołana.

Na przykład następujący kod jest zgodny ze standardami C:

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

Ale powoduje to nieokreślone zachowanie, ponieważ {[2] } nie została przekazana do foo.

W C++ istnieją dwie wersje foo: jedna, która nie pobiera argumentów i druga, która pobiera int. Więc bar Kończy wywołanie niezdefiniowanej wersji, co spowoduje błąd linkera (zakładając, że nigdzie nie ma innych definicji foo).

 21
Author: Zach Hirsch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-06 12:48:24

Powyższe odpowiedzi są całkiem poprawne, ale linkuję do doskonałej strony Davida Tribble ' a, ponieważ daje świetne Wyjaśnienie na ten i wiele innych kwestii.

The highlights:

C rozróżnia funkcję zadeklarowana z pustą listą parametrów oraz funkcja zadeklarowana za pomocą Lista parametrów składająca się tylko z pustka. Ten pierwszy jest niezabezpieczony funkcja przyjmująca nieokreśloną liczbę argumentów, podczas gdy ta ostatnia jest funkcja prototypowa przyjmowanie nie argumenty.

C++ natomiast nie sprawia, że rozróżnienie między dwoma deklaracje i rozważa je zarówno oznacza funkcję przyjmującą nie argumenty.

Dla kodu, który ma być skompilowany jako C lub c++, najlepszy rozwiązaniem tego problemu jest zawsze deklarowanie funkcji nie pobierających parametrów z jawnym prototypem void.

Prototypy pustej funkcji są deprecated feature in C99 (as they byli w C89).

Edit: po przyjrzeniu się standardowi, warto zauważyć, że składnia func (void) jest Nie przestarzała w C++, ale jest powszechnie uważana za idiom w stylu C. Myślę, że większość programistów C++, z którymi się spotkałem, woli pustą listę parametrów.

Edit 2: Dodanie cytatu ze standardu C++, sekcja 8.3.5, paragraf 2:

"jeśli parametr-deklaracja-klauzula jest pusty, funkcja nie pobiera żadnych argumentów. Lista parametrów (void) to odpowiednik pustej listy parametrów. Poza tym szczególnym przypadkiem, void nie jest typem parametru (chociaż typy pochodzące od void, takie jak void*, can)."

Nie ma wzmianki, że obie formy są przestarzałe. Jeszcze raz dziękuję doskonałej stronie Pana Tribble ' a za wskazanie mi właściwej sekcji standardu.

 17
Author: Dan Olson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-01 12:44:53

Tl; dr: użyj void.

Biorąc pod uwagę kompatybilność wsteczną w C++ i BIT niejednoznaczności zidentyfikowanej poniżej, stwierdzam, że wracamy do KnR i ANSI C dla rozstrzygającej odpowiedzi:

int getline(void);
int copy(void)

Ponieważ wyspecjalizowane wersje getline i copy nie mają argumentów, logika sugerowałaby, że ich prototypy na początku pliku powinny być getline() i copy(). Ale dla kompatybilności z starsze programy C standard przyjmuje pustą listę jako stary styl deklaracji i wyłącza sprawdzanie listy argumentów; słowo void musi być użyte dla jawnie pustej listy. [Kernighan & Richie, the C programming language, 1988, Pgs 32-33]

I..

Specjalne znaczenie pustej listy argumentów ma na celu umożliwienie starsze programy C do kompilacji z nowymi kompilatorami. Ale to zły pomysł, aby używaj go z nowymi programami. Jeśli funkcja przyjmuje argumenty, deklaruje ich; jeśli nie ma argumentów, użyj void [ibid, Str. 73]

EDIT: resztę podzieliłem na osobną dyskusję tutaj: czy określenie użycia void w deklaracji funkcji, która nie przyjmuje argumentów, odnosi się do najbardziej irytującego Parse ' a?

 2
Author: kmiklas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:37

C11 n1570 standard draft

void f() jest przestarzałe, void f(void) Zalecane:

6.11.6 deklaratoria funkcji :

1 Użycie deklaratorów funkcji z pustymi nawiasami (nie parametr prototype-format type declarators) jest funkcją przestarzałą.

wprowadzenie:

2 Niektóre funkcje są przestarzałe, co oznacza, że można je uznać za wycofanie w przyszłych rewizjach tego międzynarodowego standardu. Są one zatrzymane, ponieważ ich powszechnego stosowania, ale ich zastosowanie w nowych implementacjach (do realizacji funkcje) lub nowe programy (dla języka [6.11] lub funkcje biblioteki [7.31]) są odradzane.

Szczegółowa dyskusja: https://stackoverflow.com/a/36292431/895245

C++11 n3337 standard draft

Ani void f(void) ani void f() nie są przestarzałe.

void f(void) istnieje dla zgodności z C. Załącznik C "Zgodność" C. 1. 7 Klauzula 8: zgłaszający :

8.3.5 zmiana: w C ++ funkcja zadeklarowana z pustą listą parametrów nie pobiera argumentów. W C, pusty Lista parametrów oznacza, że liczba i typ argumentów funkcji są nieznane.

Ponieważ {[0] } jest przestarzałe w C i void f(void) zalecane, void f(void) będzie istnieć tak długo, jak C++ chce zachować kompatybilność.

void f(void) i void f() są takie same w C++. Więc dłużej void f(void) ma sens tylko wtedy, gdy zależy ci na pisaniu kodu, który kompiluje się zarówno w C, jak i c++, co prawdopodobnie nie jest tego warte.

Szczegółowa dyskusja: https://stackoverflow.com/a/36835303/895245

 1
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:37

W C++, {[0] } jest rzeczywiście przestarzałą deklaracją, która jest w 100% równoważna int f(). jest tym samym podpisem. void w tym kontekście jest tak samo znacząca jak np. spacja. Oznacza to również, że podlegają one jednej zasadzie definicji (nie przeciążają) i Derived::f(void) nadpisują Base::f().

Nie zadzieraj z takimi rzeczami jak f(const void). Nie ma zbyt wielu konsensusu co do tego rodzaju dziwactwa.

 -1
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 08:13:49