Qual é a diferença entre function () e function (void)?

27

Ouvi dizer que é uma boa prática escrever funções que não recebem nada como um parâmetro como este:

int func(void);

Mas ouvi dizer que a maneira correta de expressar isso é assim:

int func();

Qual é a diferença entre essas duas declarações de função em C e C ++?

Grizzly
fonte
5
Esta é uma duplicata de um milhar de outras perguntas sobre a rede local, entre outros stackoverflow.com/questions/18167390/...
Lars Viklund
@LarsViklund é apenas uma duplicata se houver uma dúvida neste site. Não consigo encontrar um, portanto, independentemente do que está no SO, isso não é uma duplicata. Provavelmente vale a pena manter essa pergunta como uma placa de sinalização, se nada mais.
1
@LightnessRacesinOrbit discutimos no bate - papo e decidimos manter isso por aí com algumas edições.

Respostas:

17

C e C ++ são diferentes nesse aspecto.

C 2011 Padrão Online

6.7.6.3 Declaradores de funções (incluindo protótipos)
...
10 O caso especial de um parâmetro do tipo não nomeado voidcomo o único item da lista especifica que a função não possui parâmetros.
...
14 Uma lista de identificadores declara apenas os identificadores dos parâmetros da função. 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. A lista vazia em um declarador de função que não faz parte de uma definição dessa função especifica que nenhuma informação sobre o número ou tipos de parâmetros é fornecida. 145)

Em resumo, uma lista de parâmetros vazia em uma declaração de função indica que a função aceita um número não especificado de parâmetros, enquanto uma lista de parâmetros vazia em uma definição de função indica que a função não aceita parâmetros.

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

No que diz respeito a C, você nunca deve usar uma lista de identificadores vazia em uma declaração ou definição de função . Se uma função não tiver nenhum parâmetro, especifique-o usando voidna lista de parâmetros.

Padrão C ++ on-line

8.3.5 Funções [dcl.fct]
...
4 A cláusula parâmetro-declaração- determina os argumentos que podem ser especificados e seu processamento quando a função é chamada. [ Nota: a cláusula de declaração de parâmetro é usada para converter os argumentos especificados na chamada de função; ver 5.2.2. - end note ] Se a cláusula de declaração de parâmetro estiver vazia, a função não aceita argumentos. Uma lista de parâmetros que consiste em um único parâmetro sem nome do tipo não dependente voidé equivalente a uma lista de parâmetros vazia. Exceto neste caso especial, um parâmetro não deve ter tipo cv void. Se a cláusula de declaração de parâmetrotermina com reticências ou um pacote de parâmetros de função (14.5.3), o número de argumentos deve ser igual ou maior que o número de parâmetros que não possuem um argumento padrão e não são pacotes de parâmetros de função. Onde sintaticamente correto e onde "..." não faz parte de um declarador abstrato , ", ..." é sinônimo de "...". [ Exemplo: a declaração
    int printf(const char*, ...);
declara uma função que pode ser chamada com vários números e tipos de argumentos.
    printf("hello world");
    printf("a=%d b=%d", a, b);
No entanto, o primeiro argumento deve ser de um tipo que pode ser convertido para um const char*- exemplo final ] [ Nota: O padrão de cabeçalho <cstdarg>contém um mecanismo para aceder argumentos passados usando a elipse (ver 5.2.2 e 18,10). - nota final ]

No caso de C ++, uma lista de parâmetros vazia em uma declaração ou definição indica que a função não aceita argumentos e é equivalente a usar uma lista de parâmetros de void.

John Bode
fonte
35

Em C, uma função com uma lista de parâmetros vazia ()pode levar qualquer coisa para seus argumentos. Literalmente qualquer coisa. Isso geralmente é usado para implementar uma função que pode levar um número variável de argumentos , embora atualmente seja considerado preferível usar a sintaxe de reticências mais explícita (...)para essas funções.

Em C, uma função com a lista de parâmetros (void) não aceita explicitamente nada para seus argumentos. Isso significa que o compilador pode realmente dizer que você cometeu um erro se tentar passar alguma coisa.

No C ++, essas declarações de função são equivalentes. Uma lista de parâmetros em branco significa "sem parâmetros" da mesma forma que voidfaz.

Ixrec
fonte
Re: "Isso geralmente é usado para implementar uma função que pode levar um número variável de argumentos": Você tem certeza disso? Acho que nunca vi um programa que usasse listas de parâmetros explícitas para declarações avançadas de funções não-variadicas e ()para aquelas de variáveis ​​variadas. Você tem um exemplo de um programa que usa esta convenção?
Ruakh
4
A função variável AC deve ser definida com a ...sintaxe e deve ter pelo menos um parâmetro nomeado. Definir essa função com ()causa um comportamento indefinido - e não há como o corpo da função usar as macros definidas <stdarg.h>para ler os valores dos parâmetros. Este tem sido o caso desde o padrão 1989/1990.
Keith Thompson
@ KeithThompson: Esta pergunta e esta resposta estão falando de pré-declarações, não de definições de funções.
Ruakh
3
@ruakh: Uma função variável deve ser declarada e definida usando a ...sintaxe para evitar comportamentos indefinidos.
21415 Keith Thompson