Czy istnieje różnica między foo (void) a foo () w C ++ lub C?


253

Rozważ te dwie definicje funkcji:

void foo() { }

void foo(void) { }

Czy jest jakaś różnica między tymi dwoma? Jeśli nie, to dlaczego jest voidtam ten argument? Powody estetyczne?


Dla C P / A jest tutaj
Antti Haapala

Odpowiedzi:


317

W C :

  • void foo()oznacza „funkcję foopobierającą nieokreśloną liczbę argumentów nieokreślonego typu”
  • void foo(void)oznacza „funkcję foobez argumentów”

W C ++ :

  • void foo()oznacza „funkcję foobez argumentów”
  • void foo(void)oznacza „funkcję foobez argumentów”

foo(void)Dlatego pisząc , osiągamy taką samą interpretację w obu językach i sprawiamy, że nasze nagłówki są wielojęzyczne (chociaż zwykle musimy zrobić coś więcej z nagłówkami, aby były naprawdę wielojęzyczne; mianowicie, zawijamy je, extern "C"jeśli się kompilujemy C ++).


10
Ale gdyby C ++ wymagało tego void, to mógłby uniknąć problemu „najbardziej dokuczliwej analizy”.
Adrian McCarthy

5
To prawda, ale w C ++ jest tak wiele innych kiepskich analiz, że nie ma sensu kvetchować o żadnym z nich.
DrPizza

16
W ostatnim pytaniu @James Kanze opublikował ciekawy smakołyk. Prześlij tutaj tutaj, aby go nie zgubić: pierwsze wersje C nie pozwalały na określenie liczby parametrów, które może przyjąć funkcja, dlatego void foo()była to jedyna składnia, która deklarowała funkcję. Kiedy podpisy zostały wprowadzone, komitet C musiał ujednoznacznić parametr no ze starej składni i wprowadził void foo(void)składnię. C ++ wziął to ze względu na kompatybilność.
Matthieu M.,

3
Czy możesz podać mi przykład C C90, a później gdzie użycie void foo()zamiast void foo(void)spowoduje funkcjonalną różnicę? Tj. Używam wersji bez pustki od wielu lat i nie widziałem żadnego problemu, czy coś mi umknęło?
chacham15

6
@ chacham15 void foo() { if ( rand() ) foo(5); } kompiluje się i uruchamia (powoduje niezdefiniowane zachowanie, chyba że masz dużo szczęścia), podczas gdy void foo(void)przy tym samym ciele może wystąpić błąd kompilacji.
MM

39

Zdaję sobie sprawę, że twoje pytanie dotyczy C ++, ale jeśli chodzi o C, odpowiedź można znaleźć w K&R, strony 72-73:

Ponadto, jeśli deklaracja funkcji nie zawiera argumentów, jak w

double atof();

to również oznacza, że ​​nie można nic zakładać o argumentach atof; wszystkie sprawdzanie parametrów jest wyłączone. To specjalne znaczenie pustej listy argumentów ma na celu umożliwienie starszym programom C kompilacji z nowymi kompilatorami. Ale to zły pomysł, aby używać go z nowymi programami. Jeśli funkcja przyjmuje argumenty, zadeklaruj je; jeśli nie przyjmuje żadnych argumentów, użyj void.


Ale pytanie dotyczy definicji, w takim przypadku odpowiednią regułą C jest pusta lista w deklaratorze funkcji, która jest częścią definicji tej funkcji, określa, że ​​funkcja nie ma parametrów.
jinawee

9

Wersja standardowa C ++ 11 N3337

Nie ma różnicy.

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

Załącznik C „Zgodność” C.1.7 Klauzula 8: Deklaratorzy mówią:

8.3.5 Zmiana: W C ++ funkcja zadeklarowana z pustą listą parametrów nie przyjmuje żadnych argumentów. W C pusta lista parametrów oznacza, że ​​liczba i typ argumentów funkcji są nieznane.

Przykład:

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

Uzasadnienie: Ma to na celu uniknięcie błędnych wywołań funkcji (tj. Wywołań funkcji z niewłaściwą liczbą lub rodzajem argumentów).

Wpływ na pierwotny element: przejście na semantykę dobrze zdefiniowanego elementu. Ta funkcja została oznaczona jako „przestarzała” w C.

Funkcje 8.5.3 mówią:

4. Klauzula parametr-deklaracja określa argumenty, które można określić, i ich przetwarzanie, gdy funkcja jest wywoływana. [...] Jeśli klauzula deklaracja parametru jest pusta, funkcja nie przyjmuje argumentów. Lista parametrów (void) jest równoważna pustej liście parametrów.

C99

Jak wspomniano w C ++ 11, int f()nic nie określa argumentów i jest przestarzały.

Może to prowadzić do działania kodu lub UB.

Szczegółowo zinterpretowałem standard C99 pod adresem : https://stackoverflow.com/a/36292431/895245


2

W C używasz pustki w pustym odwołaniu do funkcji, dzięki czemu kompilator ma prototyp, a ten prototyp nie ma „argumentów”. W C ++ nie musisz informować kompilatora, że ​​masz prototyp, ponieważ nie możesz go pominąć.


1
„prototyp” oznacza deklarację i typ listy argumentów. Mówię to, ponieważ „prototyp” pomylił mnie co do tego, co miałeś na myśli.
Zan Lynx
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.