Existe uma diferença entre foo (void) e foo () em C ++ ou C?

253

Considere estas duas definições de função:

void foo() { }

void foo(void) { }

Existe alguma diferença entre esses dois? Se não, por que o voidargumento está aí? Razões estéticas?

Landon
fonte
Para C a Q / A é aqui
Antti Haapala

Respostas:

317

Em C :

  • void foo()significa "uma função fooque recebe um número não especificado de argumentos de tipo não especificado"
  • void foo(void)significa "uma função fooque não aceita argumentos"

Em C ++ :

  • void foo()significa "uma função fooque não aceita argumentos"
  • void foo(void)significa "uma função fooque não aceita argumentos"

Ao escrever foo(void), portanto, obtemos a mesma interpretação nos dois idiomas e tornamos nossos cabeçalhos multilíngues (apesar de geralmente precisarmos fazer mais algumas coisas com os cabeçalhos para torná-los realmente com linguagem cruzada; ou seja, envolvê-los em um extern "C"se estiver compilando C ++).

DrPizza
fonte
10
Mas se o C ++ exigisse o void, então ele poderia ter evitado o problema "análise mais irritante".
Adrian McCarthy
5
É verdade, mas existem tantas outras análises ruins no C ++ que não há nenhum ponto real no kvetching sobre qualquer uma delas.
DrPizza
16
Em uma pergunta recente, @James Kanze postou um boato interessante. Repita aqui para evitar perdê-lo: as primeiras versões de C não permitiram especificar o número de parâmetros que uma função poderia ter, portanto, void foo()era a única sintaxe a declarar uma função. Quando as assinaturas foram introduzidas, o comitê C teve que desambiguar o parâmetro sem da sintaxe antiga e introduziu a void foo(void)sintaxe. O C ++ tomou isso por uma questão de compatibilidade.
Matthieu M.
3
Você pode me dar um exemplo de C C90 e, posteriormente, onde o uso em void foo()vez de void foo(void)produzirá uma diferença funcional? Ou seja, eu tenho usado a versão sem o vazio por muitos anos e não vi nenhum problema, estou perdendo alguma coisa?
precisa saber é o seguinte
6
@ chacham15 void foo() { if ( rand() ) foo(5); } compila e executa (causando comportamento indefinido, a menos que você tenha muita sorte), enquanto que void foo(void)o mesmo corpo causaria um erro de compilação.
MM
39

Sei que sua pergunta pertence ao C ++, mas quando se trata de C, a resposta pode ser encontrada em K&R, páginas 72-73:

Além disso, se uma declaração de função não incluir argumentos, como em

double atof();

isso também significa que nada deve ser assumido sobre os argumentos de atof; toda a verificação de parâmetros está desativada. Esse significado especial da lista de argumentos vazia destina-se a permitir que programas C mais antigos sejam compilados com novos compiladores. Mas é uma má idéia usá-lo com novos programas. Se a função receber argumentos, declare-os; se não houver argumentos, use void.

Kyle Cronin
fonte
Mas a questão é sobre definições; nesse caso, a regra C relevante é: Uma lista vazia em um declarador de função que faz parte de uma definição dessa função especifica que a função não possui parâmetros.
jinawee
9

Rascunho padrão do C ++ 11 N3337

Não há diferença.

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

Anexo C "Compatibilidade" C.1.7 Cláusula 8: os declaradores declaram :

8.3.5 Alteração: no C ++, uma função declarada com uma lista de parâmetros vazia não aceita argumentos. Em C, uma lista de parâmetros vazia significa que o número e o tipo dos argumentos da função são desconhecidos.

Exemplo:

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

Fundamentação da petição: É para evitar chamadas de função incorretas (ou seja, chamadas de função com o número ou tipo de argumentos errado).

Efeito no recurso original: mude para a semântica do recurso bem definido. Esse recurso foi marcado como "obsoleto" em C.

8.5.3 funções diz:

4. A cláusula de declaração de parâmetro determina os argumentos que podem ser especificados e seu processamento quando a função é chamada. [...] Se a cláusula de declaração de parâmetro estiver vazia, a função não aceita argumentos. A lista de parâmetros (nula) é equivalente à lista de parâmetros vazia.

C99

Conforme mencionado pelo C ++ 11, int f()não especifica nada sobre os argumentos e é obsoleto.

Pode levar ao código de trabalho ou UB.

Interpretei o padrão C99 em detalhes em: https://stackoverflow.com/a/36292431/895245

Ciro Santilli adicionou uma nova foto
fonte
2

Em C, você usa um vazio em uma referência de função vazia para que o compilador tenha um protótipo e esse protótipo "não tenha argumentos". No C ++, você não precisa informar ao compilador que possui um protótipo porque não pode deixar de fora o protótipo.

Paul Tomblin
fonte
1
"protótipo" significa a declaração da lista de argumentos e o tipo de retorno. Digo isso porque "protótipo" me confundiu sobre o que você quis dizer no começo.
Zan Lynx