Pergunta

Atualmente, estou refatorando/arrumando algum código C antigo usado em um projeto C ++ e vendo regularmente funções como:

int f(void)

que eu tenderia a escrever como:

int f()

Existe algum motivo para não substituir (nulo) por () em toda a base de código para melhorar a consistência ou há uma diferença sutil entre os dois dos quais não tenho conhecimento? Mais especificamente, se uma função de membro virtual em C ++ for descrita como:

virtual int f(void)

e uma classe derivada inclui uma função de membro:

int f()

Esta é uma substituição válida? Além disso, é provável que encontre problemas de vinculador com base em assinaturas quase idênticas?

Foi útil?

Solução

Em c, a declaração int f(void) significa uma função retornando int que não leva parâmetros. A declaração int f() significa uma função retornando int que leva qualquer número de parâmetros. Assim, se você tem uma função que não leva parâmetros em C, o primeiro é o protótipo correto.

Em C ++, eu acredito int f(void) está preterido e int f() é preferido, pois significa especificamente uma função que não leva parâmetros.

Outras dicas

Para adicionar à resposta de Chris, usando int f() é uma prática ruim em C, na minha experiência, já que você perde a capacidade do compilador de comparar a declaração da função com sua definição, para garantir que ela seja chamada corretamente.

Por exemplo, o código a seguir é compatível com os padrões C:

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

Mas resulta em comportamento indefinido, já que a não foi passado para foo.

Em C ++, existem duas versões de foo: um que não leva argumentos e um que leva um int. Então bar acaba chamando a versão indefinida, o que resultaria em um erro de vinculador (assumindo que não há outras definições de foo qualquer lugar).

As respostas acima estão bastante corretas, mas estou ligando para a excelente página de David Tribble, pois dá um Grande explicação sobre isso e muitas outras questões.

Os destaques:

C distingue entre uma função declarada com uma lista de parâmetros vazios e uma função declarada com uma lista de parâmetros que consiste apenas no vazio. O primeiro é uma função desprotipada, levando um número não especificado de argumentos, enquanto o último é uma função prototipada sem argumentos.

O C ++, por outro lado, não faz distinção entre as duas declarações e considera que ambas significam uma função que não está levando argumentos.

Para o código que se destina a ser compilado como C ou C ++, a melhor solução para esse problema é sempre declarar funções que não recebem parâmetros com um protótipo vazio explícito.

Os protótipos de função vazia são um recurso depreciado no C99 (como estavam no C89).

Editar: Depois de olhar para o padrão, talvez valha a pena notar que a sintaxe Func (void) é não Conseguido em C ++, mas é comumente considerado mais um idioma no estilo C. Eu acho que a maioria dos programadores C ++ que eu encontro prefere a lista de parâmetros vazios.

Edit 2: Adicionando uma cotação do padrão C ++, Seção 8.3.5, parágrafo 2:

"Se a cláusula de declarações de parâmetro estiver vazia, a função não leva argumentos. A lista de parâmetros (void) é equivalente à lista de parâmetros vazios. Exceto para este caso especial, o vazio não deve ser um tipo de parâmetro (embora tipos derivados do vazio , como void*, pode). "

Não há menção de que qualquer um dos formulários esteja depreciado. Mais uma vez obrigado ao excelente site do Sr. Tribble por me apontar para a seção correta do padrão.

tl; dr: use void.

Dada a compatibilidade com versões anteriores em C ++, e a parte da ambiguidade identificada abaixo, afirmo que voltamos até o KNR e Ansi C para uma resposta conclusiva:

int getline(void);
int copy(void)

Como as versões especializadas do getLine e cópia não têm argumentos, a lógica sugere que seus protótipos no início do arquivo devem ser getline() e copy(). Mas, para compatibilidade com os programas C mais antigos, o padrão assume uma lista vazia como uma declaração de estilo antigo e desliga todas as verificações da lista de argumentos; a palavra void deve ser usado para uma lista explicitamente vazia. [Kernighan & Richie, The C Programming Language, 1988, PGS 32-33

e..

O significado especial da lista de argumentos vazios destina -se a permitir que os programas C mais antigos compilem com novos compiladores. Mas é uma má idéia usá -lo com novos programas. Se a função assumir argumentos, declare -os; Se não for argumentos, use void [ibid, pág. 73

Editar: quebrou o resto em uma discussão separada aqui:Especificar o uso do vazio na declaração de uma função que não leva argumentos aborda a análise mais irritante?

C11 N1570 RASSH STANDARD

void f() está preterido, void f(void) recomendado:

6.11.6 Declaradores de função:

1 O uso de declaradores de função com parênteses vazios (não declaradores do tipo de parâmetro de formato de protótipo) é um recurso obsoleto.

Introdução:

2 Certas características são obsoletas, o que significa que elas podem ser consideradas para retirada em revisões futuras desse padrão internacional. Eles são mantidos por causa de seu uso generalizado, mas seu uso em novas implementações (para recursos de implementação) ou novos programas (para os recursos de idioma [6.11] ou biblioteca [7.31]) é desencorajado.

Discussão detalhada: https://stackoverflow.com/a/36292431/895245

C ++ 11 N3337 rascunho padrão

Nenhum void f(void) nem void f() são preteridos.

void f(void) Existe para compatibilidade com C. Anexo C "Compatibilidade" C.1.7 Cláusula 8: Declaradores:

8.3.5 Alteração: em C ++, uma função declarada com uma lista de parâmetros vazios não leva argumentos. Em C, uma lista de parâmetros vazios significa que o número e o tipo de argumentos de função são desconhecidos.

Desde void f() é preterido em C e void f(void) recomendado, void f(void) existirá enquanto o C ++ quiser manter a compatibilidade.

void f(void) e void f() são os mesmos em C ++. Então, mais tempo void f(void) Só faz sentido se você se preocupa com o código que compila em C e C ++, o que provavelmente não vale a pena.

Discussão detalhada: https://stackoverflow.com/a/36835303/895245

Em C ++, int f(void) é de fato uma declaração depreciada que é 100% equivalente a int f(). Isto é a mesma assinatura. o void Nesse contexto, é tão significativo quanto o espaço em branco. Isso também significa que eles estão sujeitos à regra de uma definição (eles não sobrecarregam) e Derived::f(void) substituir Base::f().

Não mexa com coisas como f(const void), no entanto. Não há muito consenso o que esse tipo de estranheza significa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top