Não é necessário um ponto-e-vírgula (';') após uma declaração de função em C ++?

174

Recentemente, fiz um teste de programação intermediária e uma das perguntas erradas foi a seguinte:

Um ponto e vírgula (';') não é necessário após uma declaração de função.

Verdadeiro ou falso.

Eu escolhi "false" (e corrija-me se estiver errado porque sinto que estou ficando louco), uma declaração de função é o que você escreve antes da definição (na parte superior do código) para que o compilador conheça a função antes mesmo de chamá-lo, e uma definição de função é o que compõe a função como um todo.

Ou seja,

Declaração:

int func();

Definição:

int func() {
  return 1;
}

A resposta não deveria ser falsa?

Logan
fonte
41
Uma definição também é uma declaração. Mas eu diria que sua resposta estava correta.
216
É uma pergunta complicada e não tem nenhuma influência na capacidade de alguém para programar bem.
phonetagger
40
Eu sempre acho as perguntas que resultam em duplo negativo, confusas. Na minha opinião, essas perguntas são projetadas para enganar os alunos. Por que a pergunta não pôde ser formada da seguinte maneira: "Um ponto-e-vírgula (';') é sempre necessário após uma declaração de função. Verdadeiro ou Falso."? : /
Algirdas Preidžius
18
@phonetagger Toda essa confusão mostra como a pergunta está mal formulada.
François Andrieux
34
A Navalha de Hanlon sugere que o autor do teste misturasse "declaração" e "definição".
Sneftel

Respostas:

161

Você pode ter uma situação em que declara e define a função em uma etapa, ou seja, se incluir a definição da função no ponto em que a declara. Então, tecnicamente , suponho que true esteja correto. Mas a pergunta está formulada de tal maneira que eu teria respondido da maneira que você fez.

jwismar
fonte
10
Eu diria que a verdade não está correta por causa do motivo que você deu. Se houver casos em que um ponto-e-vírgula é necessário, será falso (ou não verdadeiro). Verdadeiro é o absoluto para mim, se houver casos claros quando necessário, você não poderá dizer que é verdade.
I Funball 21/02/19
16
@IFunball Bom argumento. Línguas natuais estúpidas. A frase "Um ponto e vírgula (';') não é necessária após uma declaração de função" pode ser lida como "Um ponto e vírgula (';') não é (sempre) necessária após uma declaração de função" ou como "Um ponto e vírgula (';' ) não é (sempre) necessário após uma declaração de função ". A qualificação da afirmação como verdadeira ou falsa depende da escolha de uma interpretação. Estritamente falada, a pergunta não é clara e, portanto, não tem resposta clara.
Peter - Restabelece Monica
6
@IFunball É porque "declaração", sem outro contexto e nenhuma declaração de que somos advogados de linguagem, é comumente entendido como "uma declaração não definidora". A pergunta era injusta.
Lightness Races in Orbit -
2
Qualquer pergunta do exame que não seja clara para alguém que conhece o conteúdo que está sendo testado está com erros.
25419 Nat
2
Parece que precisamos adicionar uma cláusula de comportamento indefinida ao idioma inglês
Nick Mertin
147

Além da coisa "uma definição também é uma declaração", o seguinte é C ++ legal:

int f(), g();

Isso declara duas funções fe g, ambas sem argumentos e com um tipo de retorno de int, mas a definição de fnão é seguida (imediatamente) por um ponto e vírgula. Da mesma forma, isso é legal:

int f(), i = 42;

Mas, de fato, não é permitido omitir o ponto-e-vírgula inteiramente nesses casos; portanto, seria algo surpreendente se um deles fosse tomado como exemplo de uma declaração sem o ponto-e-vírgula seguinte. De fato, o seguinte é ilegal:

void *p, f() {}

Além de uma (mera) declaração de função, uma definição de função não pode ser combinada com nenhuma outra declaração ou definição para o mesmo especificador de tipo . (Se isso fosse legal, definiria a void *pe a void f() {}.)

De qualquer forma, esse parece ser um tipo de pergunta "pegadinha" que não deve estar em um teste de programação intermediário.

(Ah, a propósito, por favor, não escreva código como esse int f(), i = 42;.)

Arne Vogel
fonte
2
Também é possível usar um typedef para definir um tipo de função e, em seguida, usá-lo para declarar muitas funções ao mesmo tempo, por exemplo, typedef int fooProc(int); fooProc a,b.c.d.e;não sei por que os cabeçalhos padrão dos compiladores baseados em unidades de disquete não fizeram isso de volta no dia, pois eu pensaria que isso permitiria que os arquivos de cabeçalho fossem bem menores e, portanto, mais rápidos de processar.
Supercat
Considere também int f(int(&g)(),int(*h)()){return g()+h();}Este possui três declarações de função, uma das quais é seguida por uma chave aberta, outra por vírgula e a terceira por um parêntese próximo.
David Hammen 23/02/19
1
@ DavidHammen: Isso não declara estritamente outras funções que não int f(stuff). Mesmo no escopo da função, gé uma variável automática do tipo referência à função e hé um ponteiro para a função .
Peter Cordes
83

As outras respostas e comentários apontam várias das muitas maneiras pelas quais essa é uma pergunta horrível, enganosa e mal escrita. Mas há outro problema que ninguém mais identificou ainda. A questão é:

Um ponto e vírgula (';') não é necessário após uma declaração de função. Verdadeiro ou falso.

OK, vamos olhar para uma declaração de função:

int func();       /* */
/*           ^       */
/*           |       */
/* That whitespace is "after the function declaration". */

Essa coisa toda é a declaração . A declaração não é int func()e depois é seguida por a ;. A declaração é int func();e, em seguida, é seguida por espaço em branco.

Então, a pergunta é: é necessário um ponto e vírgula após a declaração ? Claro que não. A declaração já possui um ponto-e-vírgula e a encerrou. Um ponto e vírgula após a declaração seria inútil. Por outro lado, int func(); ;seria um ponto e vírgula após uma declaração de função .

A pergunta quase certamente pretendia fazer a pergunta "verdadeira ou falsa: o último token em uma declaração de função é sempre um ponto e vírgula". Mas essa não é a pergunta que eles escreveram, porque o autor do questionário não estava pensando claramente sobre o problema.

Meu conselho é evitar completamente os testes de linguagem de programação. Eles são horríveis.


Curiosidade, enquanto estamos sobre o assunto. Em C #, tudo isso é legal:

class C {}
class D {};
struct E {}
struct F {};

Em C #, uma declaração de classe ou estrutura pode terminar em ponto e vírgula, ou não, a seu critério. Esse pequeno recurso estranho foi adicionado para o benefício dos programadores de C / C ++ que chegam ao C # que têm na ponta dos dedos que as declarações de tipo terminam em ponto e vírgula; a equipe de design não queria puni-los por terem esse hábito. :-)

Eric Lippert
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Samuel Liew
25

Você também pode declarar uma função como esta:

int func(){
    return 1;
}

A afirmação é muito ambígua. A resposta certa deve ser: depende de como você declara a função.

Enfim, eu teria escolhido falso também, e talvez você possa relatar a pergunta a alguém.

Luca Corsini
fonte
3
De qualquer forma, não coloque a coisa em um nível pessoal. O importante é que você entendeu como funciona uma função declaração de definição, então não se preocupe muito sobre isso, apenas certifique-se que a questão será, pelo menos verificado e ir
Luca Corsini
11
Absolutamente. Honestamente, eu aprendi mais sobre definição de declaração de função ao errar a pergunta do que eu teria feito se estivesse correto.
Logan
1
@Logan não se preocupe muito. Se você sabe escrever e ler uma função, é tudo o que precisa. Eu pessoalmente odeio esse tipo de pergunta que 1. não está bem definida 2. teste seu conhecimento teórico da sintaxe. Para mim, é como memória muscular. Quando escrevo cada dígito vai sem esforço para a tecla que deveria, mas se você me der um teste sobre quais teclas deve pressionar um dígito, ficaria completamente sem esperança sem um teclado para executar fisicamente a ação ...
bolov
2
... Escrever sintaxe comum (por exemplo, como uma função) se tornará uma segunda natureza para você. E quando você vai estragar tudo porque acabou de mudar de idioma, bem ... o realce de sentido e sintaxe cria soluções rápidas e eficientes. Invista seu tempo e energia em algo mais útil.
bolov 20/02/19
20

Um ponto e vírgula (';') não é necessário após uma declaração de função.

Verdadeiro ou falso.

Verdadeiro . Um ponto-e-vírgula não é necessário após qualquer declaração. Nem depois de qualquer definição. Nem depois de qualquer declaração.

Muitos tipos de declaração precisam terminar com ponto e vírgula, conforme especifica a sintaxe na seção 7 [dcl.dcl]. Mas nunca há necessidade de escrever um segundo depois disso.

Marc van Leeuwen
fonte
1
Vejo que Eric Lippert já discutiu esse ponto. Eu acho que todos os votos positivos me fizeram ignorar. Sinta-se livre para votar lá.
Marc van Leeuwen
Praticamente qualquer pergunta que pergunte: "X é sempre verdadeiro: verdadeiro ou falso?" vai ter a resposta "false". Caramba, não há necessidade de ponto e vírgula em qualquer lugar ; o compilador pode reclamar e se recusar a compilar seu programa, mas esse não é o fim do mundo; Eu não chamaria isso de uma necessidade fundamental . ;)
Quuxplusone 23/02/19
@Quuxplusone se o compilador rejeita seu programa, seu programa não tem nenhum declarações de função em que :)
Ben Millwood
6

Isso depende se estamos declarando ou definindo a função. Se estamos declarando a função, precisamos incluir o ponto e vírgula ( ;) e, se estamos definindo a função, o ponto e vírgula não é necessário.

Uma declaração é assim:

int add(int, int);

E uma definição é assim:

int add(int a, int b)
{
    // ...
}
Rocx En Ruff
fonte
10
O problema com esta resposta é que ela sugere que definições e declarações são mutuamente exclusivas. De fato, toda definição é uma declaração; definições são um subconjunto de declarações.
MSalters 21/02/19
6

Embora eu concorde com quase todas as outras respostas, afirmando que a pergunta é redigida de forma muito ambígua e que sua resposta é tecnicamente correta, permita-me dar uma perspectiva diferente:

É assim que eu sempre os chamei:

void func();  // The function prototype

...

void func()
{
    // The function definition
}

Estou assumindo que a pergunta foi feita com essa terminologia em mente.

Definição e declaração são o mesmo conceito aos meus olhos. "Eu defino x = y" == "Declaro x = y".

Mas é claro que há uma grande diferença entre o protótipo da função (na parte superior) e a definição real da função.

Opifex
fonte
Para mim, seu protótipo é a declaração baseada em como eu aprendi (embora não esteja dizendo que você está errado), mas também esperaria que um protótipo especifique o número e o tipo de argumentos, ou será nulo, mas espero que você tenha omitido isso. por brevidade.
22419 David S
David S: Sim, é claro que também conteria o número e o tipo de argumentos, mas eu os omiti por questões de brevidade (observe que também não há argumentos na declaração real da função). No entanto, eu realmente não concordo quando você diz que a declaração completa da função é chamada de protótipo. Cito a Wikipedia: "um protótipo de função ou interface de função é uma declaração de uma função que especifica o nome e a assinatura do tipo de função (arity, tipos de dados de parâmetros e tipo de retorno), mas omite o corpo da função".
Opifex 22/02/19
@ David: No C ++, declarações de função são sempre protótipos (ou definições) e void func();são exatamente equivalentes a void func(void);. Isso é muito diferente de C , onde void func();não diz nada ao compilador sobre os argumentos e não é a mesma coisa que void func(void);. Um protótipo ou definição posterior é uma boa idéia; caso contrário, o chamador deve aplicar as promoções arg padrão (por exemplo, tipos inteiros float -> double e narrow para int. As mesmas regras que args para funções variadas.)
Peter Cordes
Minhas desculpas, acabei aqui olhando para algo relacionado a C e não percebi a mudança de linguagem. Não vou excluir meu comentário por motivos de clareza, mas considero que ele foi retirado.
David S
6

É uma pena que a pergunta que você fez não diga "diretamente depois". Por exemplo, poderíamos escrever isso:

int func()  /* My function */ ;

Ou eu poderia escrever:

int func()
int a = 42;

No primeiro caso, o ponto-e-vírgula não está diretamente após a declaração, mas seria bom.

No segundo caso, há um ponto e vírgula "após" a declaração, mas não diretamente após.

Acho que Eric Lippert tem a idéia certa em sua resposta .

É como dizer "deve haver um período após o final de uma frase em inglês?". Indiscutivelmente, uma frase já tem um ponto final no final (caso contrário, não seria uma frase) e, portanto, não deve haver um período após a frase.

Nick Gammon
fonte
4
Agradável. Terminar essa frase com um período extra. Eu vi o que você fez lá.
22619 David S
2
int func() int a=42;não compila. Você precisa de uma vírgula, não de outra int. Veja a resposta de @ Arne postada mais de um dia antes disso. A única coisa nova nesta resposta é o último parágrafo, com a analogia das frases em inglês.
Peter Cordes
1
Não disse o segundo exemplo compilado. Eu estava apontando que dizer que um ponto e vírgula era necessário "depois" da declaração era ambíguo. Meu exemplo teve um ponto-e-vírgula após a declaração, mas não é compilado.
Nick Gammon
1
Esse mesmo problema ocorre nas mensagens de erro; um exemplo favorito do C # é " Um parâmetro params deve ser o último parâmetro em uma lista formal de parâmetros ". Agora, suponha que eu disse "Um sapo deve ser o último gloob de uma lista de gloob". Isso significa (1) toda lista gloob tem exatamente um frob no final, como toda pergunta tem exatamente um ponto de interrogação no final, (2) uma lista gloob pode ter qualquer número de frobs, mas se tiver um ou mais , o último item deve ser um FROB, como um número ainda pode ter qualquer número de 02468, mas uma das deve ser o último, ou ...
Eric Lippert
... (3) uma lista gloob pode ter zero ou um sapo, e se tiver um, aparece no final? Se você não conhece o contexto, eu acho que (1) é a explicação mais sensata, mas no caso de "parâmetro params", (3) é a explicação correta. Muitas descrições informais dos elementos da linguagem de programação possuem uma propriedade que meus amigos do editor técnico chamam de "COIK" - Limpar somente se conhecido. Se você ainda não entendeu o material completamente, uma descrição dele é inútil para você, mas se você já o entendeu completamente, não precisa da descrição!
Eric Lippert
4

Você pode usar ;apenas para protótipos.

M7off
fonte
4

É uma pergunta meio complicada, mas eles usaram a palavra declaração, que significa algo como isto:

int example();

Então é verdade neste caso.

Se eles usassem a palavra implementação , isso seria falso.

dark_3nergy
fonte
2

O ponto e vírgula (;) é usado para informar ao compilador que após esse ponto e vírgula (;) uma nova instrução é iniciada.

Então, acho que o ponto e vírgula (;) é necessário apenas durante uma declaração de função. Então, de acordo com mim, a resposta será verdadeira.

Jatinder
fonte
Porém, declarações não são declarações.
HolyBlackCat
mas após a declaração da função, estamos executando uma nova linha de código usando o compilador. então, acho que antes de executar uma nova linha de compilador de código, é necessário saber onde a linha anterior termina apenas para que um compilador possa gerar código nativo (ou seja, 0101).
Jatinder
2

Quando as funções são definidas antes de main () :

  • Não precisa de ponto e vírgula porque a função já está definida

Quando as funções são definidas após main () :

  • Precisa de ponto e vírgula, porque você está criando um protótipo dessa função e informando ao compilador que a função sai.
shiv shah
fonte