Jaka jest różnica między funkcją () a funkcją (void)?

27

Słyszałem, że dobrą praktyką jest pisanie funkcji, które nie otrzymują niczego jako takiego parametru:

int func(void);

Ale słyszę, że właściwy sposób wyrażenia tego jest następujący:

int func();

Jaka jest różnica między tymi dwiema deklaracjami funkcji zarówno w C, jak i C ++?

Siwy
źródło
5
Jest to duplikat tysiąca innych pytań w sieci witryn, między innymi stackoverflow.com/questions/18167390/...
Lars Viklund
@LarsViklund to tylko duplikat, jeśli na tej stronie jest pytanie. Nie mogę go znaleźć, więc niezależnie od tego, co jest na SO, nie jest to duplikat. Prawdopodobnie warto zachować to pytanie jako drogowskaz, jeśli nic więcej.
1
@LightnessRacesinOrbit omawialiśmy na czacie i postanowiliśmy go utrzymać z kilkoma zmianami.

Odpowiedzi:

17

C i C ++ różnią się pod tym względem.

C 2011 Online Standard

6.7.6.3 Deklaratory funkcji (w tym prototypy)
...
10 Szczególny przypadek nienazwanego parametru typu voidjako jedynej pozycji na liście określa, że ​​funkcja nie ma parametrów.
...
14 Lista identyfikatorów deklaruje tylko identyfikatory parametrów funkcji. Pusta lista w deklaratorze funkcji, która jest częścią definicji tej funkcji, określa, że ​​funkcja nie ma parametrów. Pusta lista w deklaratorze funkcji, która nie jest częścią definicji tej funkcji, określa, że ​​nie podano informacji o liczbie lub typach parametrów. 145)

Krótko mówiąc, pusta lista parametrów w deklaracji funkcji wskazuje, że funkcja przyjmuje nieokreśloną liczbę parametrów, a pusta lista parametrów w definicji funkcji wskazuje, że funkcja nie przyjmuje parametrów.

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

Jeśli chodzi o C, nigdy nie należy używać pustej listy identyfikatorów w deklaracji lub definicji funkcji. Jeśli funkcja nie ma przyjmować żadnych parametrów, określ ją, używając jej voidna liście parametrów.

Internetowy standard C ++

8.3.5 Funkcje [dcl.fct]
...
4 Klauzula-parametr-klauzula określa argumenty, które można określić, oraz ich przetwarzanie, gdy funkcja jest wywoływana. [ Uwaga: parametr deklaracja-klauzula służy do konwersji argumenty podane w wywołaniu funkcji; patrz 5.2.2. - uwaga końcowa ] Jeśli klauzula deklaracji parametru jest pusta, funkcja nie przyjmuje argumentów. Lista parametrów składająca się z jednego nienazwanego parametru typu niezależnego voidjest równoważna pustej liście parametrów. Z wyjątkiem tego szczególnego przypadku parametr nie może mieć typu cv void. Jeśli parametr-deklaracja-klauzulakończy się wielokropkiem lub pakietem parametrów funkcji (14.5.3), liczba argumentów powinna być równa lub większa niż liczba parametrów, które nie mają domyślnego argumentu i nie są pakietami parametrów funkcji. Tam, gdzie poprawna składniowo i gdzie „...” nie jest częścią abstrakcyjnego deklaratora , „, ...” jest synonimem „…”. [ Przykład: deklaracja
    int printf(const char*, ...);
deklaruje funkcję, którą można wywoływać przy użyciu różnych liczb i typów argumentów.
    printf("hello world");
    printf("a=%d b=%d", a, b);
Jednak pierwszy argument musi być typu, który można przekonwertować na przykładconst char* - koniec ] [ Uwaga: Standardowy nagłówek <cstdarg>zawiera mechanizm dostępu do argumentów przekazywanych za pomocą wielokropka (patrz 5.2.2 i 18.10). - uwaga końcowa ]

W przypadku C ++ pusta lista parametrów w deklaracji lub definicji wskazuje, że funkcja nie przyjmuje żadnych argumentów i jest równoważna z użyciem listy parametrów void.

John Bode
źródło
35

W C funkcja z pustą listą parametrów ()może przyjąć dowolne argumenty. Dosłownie wszystko. Jest to zwykle używane do implementacji funkcji, która może przyjmować zmienną liczbę argumentów , choć w dzisiejszych czasach uważa się za wskazane stosowanie bardziej wyraźnej składni elipsy (...)dla tych funkcji.

W C funkcja z listą parametrów (void)jawnie nie przyjmuje żadnych argumentów. Oznacza to, że kompilator może powiedzieć ci, że popełniłeś błąd, jeśli próbujesz coś przekazać.

W C ++ te deklaracje funkcji są równoważne. Pusta lista parametrów oznacza „brak parametrów” tak samo jak void.

Ixrec
źródło
Re: „Jest to zwykle używane do implementacji funkcji, która może przyjmować zmienną liczbę argumentów”: Czy jesteś tego pewien? Nie sądzę, że kiedykolwiek widziałem program, który używałby jawnych list parametrów do deklaracji w przód funkcji innych niż variadic i ()dla funkcji variadic. Czy masz przykład programu korzystającego z tej konwencji?
ruakh
4
Funkcja wariadyczna AC musi być zdefiniowana ...składnią i musi mieć co najmniej jeden nazwany parametr. Zdefiniowanie takiej funkcji ()powoduje niezdefiniowane zachowanie - a treść funkcji nie może użyć makr zdefiniowanych w <stdarg.h>celu odczytania wartości parametru. Tak jest od standardu 1989/1990.
Keith Thompson,
@KeithThompson: To pytanie i ta odpowiedź dotyczą wstępnych deklaracji, a nie definicji funkcji.
ruakh
3
@ruakh: Funkcja variadic musi zostać zadeklarowana i zdefiniowana przy użyciu ...składni, aby uniknąć niezdefiniowanego zachowania.
Keith Thompson,