Non è necessario un punto e virgola (';') dopo una dichiarazione di funzione in C ++?


174

Di recente ho svolto un test di programmazione intermedio e una delle domande che ho sbagliato era la seguente:

Un punto e virgola (';') non è necessario dopo una dichiarazione di funzione.

Vero o falso.

Ho scelto "false" (e per favore correggimi se sbaglio perché sento che sto impazzendo), una dichiarazione di funzione è ciò che scrivi prima della definizione (nella parte superiore del codice) in modo che il compilatore conosca la funzione chiama prima ancora di chiamarla, e una definizione di funzione è ciò che costituisce la funzione nel suo insieme.

Vale a dire,

Dichiarazione:

int func();

Definizione:

int func() {
  return 1;
}

La risposta a questo non dovrebbe essere falsa?


41
Una definizione è anche una dichiarazione. Ma direi che la tua risposta era corretta.

216
È una domanda complicata e non influisce sulla capacità di nessuno di programmare bene.
Fonagger,

40
Trovo sempre le domande, che risultano in doppi negativi, confuse. Nella mia mente, tali domande sono progettate per inciampare gli studenti. Perché la domanda non può essere formata nel modo seguente: "Un punto e virgola (';') è sempre necessario dopo una dichiarazione di funzione. Vero o falso."? : /
Algirdas Preidžius

18
@phonetagger Tutta questa confusione va a dimostrare quanto la domanda sia formulata male.
François Andrieux,

34
Hanlon's Razor suggerisce che l'autore del test abbia confuso "dichiarazione" e "definizione".
Sneftel,

Risposte:


161

Puoi avere una situazione in cui dichiari e definisci la funzione in un solo passaggio, cioè se includi la definizione della funzione nel punto in cui la stai dichiarando. Quindi tecnicamente suppongo che il vero sia corretto. Ma la domanda è formulata in modo tale che avrei risposto come hai fatto tu.


10
Direi che true non è corretto a causa del motivo che hai indicato. Se ci sono casi in cui è necessario un punto e virgola, allora è falso (o non vero). Vero è l'assoluto per me, se ci sono casi chiari quando è necessario, allora non puoi dire vero.
I Funball,

16
@IFunball Buona discussione. Stupide lingue native. La frase "Un punto e virgola (';') non è necessaria dopo una dichiarazione di funzione" può essere letta come "Un punto e virgola (';') non è (mai) necessario dopo una dichiarazione di funzione" o come "Un punto e virgola (';' ) non è (sempre) necessario dopo una dichiarazione di funzione ". Se qualificare l'affermazione come vera o falsa cerniera sulla scelta di un'interpretazione. A rigor di termini la domanda non è chiara e quindi non ha una risposta chiara.
Peter - Ripristina Monica il

6
@IFunball È perché "dichiarazione", senza ulteriori contesti e senza alcuna affermazione che siamo un avvocato linguista, è comunemente intesa come "una dichiarazione non definitiva". La domanda era ingiusta.
Razze di leggerezza in orbita

2
Qualsiasi domanda d'esame che non è chiara a qualcuno che conosce il contenuto per il quale viene testato viene risolta.
Nat

2
Sembra che dobbiamo aggiungere una clausola di comportamento indefinita alla lingua inglese
Nick Mertin,

147

Oltre a "una definizione è anche una dichiarazione", il C ++ legale è il seguente:

int f(), g();

Questo dichiara due funzioni fe g, entrambe senza argomenti e con un tipo restituito di int, ma la definizione di fnon è seguita (immediatamente) da un punto e virgola. Allo stesso modo, questo è legale:

int f(), i = 42;

Ma in questi casi non è consentito omettere del tutto il punto e virgola, quindi sarebbe piuttosto sorprendente se uno dei due fosse preso come esempio di una dichiarazione senza un punto e virgola successivo. In effetti, quanto segue è illegale:

void *p, f() {}

A parte una (semplice) dichiarazione di funzione, una definizione di funzione non può essere combinata con qualsiasi altra dichiarazione o definizione allo stesso identificatore di tipo . (Se questo fosse legale, definirebbe sia a void *pche a void f() {}.)

In ogni caso, questo sembra essere un tipo di domanda "gotcha" che non dovrebbe essere in un test di programmazione intermedio.

(Oh, a proposito, per favore non scrivere codice come int f(), i = 42;.)


2
È anche possibile utilizzare un typedef per definire un tipo di funzione, quindi utilizzarlo per dichiarare contemporaneamente molte funzioni, ad esempio typedef int fooProc(int); fooProc a,b.c.d.e;non sono sicuro del perché le intestazioni standard per i compilatori basati su floppy drive non lo abbiano fatto nel giorno, poiché penserei che avrebbe permesso che i file di intestazione fossero molto più piccoli e quindi più veloci da elaborare.
supercat,

Considera anche int f(int(&g)(),int(*h)()){return g()+h();}Questo ha tre dichiarazioni di funzione, una delle quali è seguita da una parentesi graffa aperta, un'altra da una virgola e una terza da una parentesi stretta.
David Hammen,

1
@DavidHammen: Questo non dichiara in modo rigoroso funzioni diverse da int f(stuff). Anche nell'ambito della funzione, gè una variabile automatica di tipo riferimento alla funzione ed hè un puntatore alla funzione .
Peter Cordes,

83

Le altre risposte e commenti evidenziano molti dei molti modi in cui questa è una domanda orribile, fuorviante e mal scritta. Ma c'è un altro problema che nessun altro ha ancora identificato. La domanda è:

Un punto e virgola (';') non è necessario dopo una dichiarazione di funzione. Vero o falso.

OK, diamo un'occhiata a una dichiarazione di funzione:

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

L'intera cosa è la dichiarazione . La dichiarazione non è int func()e quindi seguita da a ;. La dichiarazione è int func();e quindi è seguita da uno spazio bianco.

Quindi, la domanda è: è necessario un punto e virgola dopo la dichiarazione ? Ovviamente no. La dichiarazione contiene già un punto e virgola che l'ha terminata. Un punto e virgola dopo la dichiarazione sarebbe inutile. Al contrario, int func(); ;sarebbe un punto e virgola dopo una dichiarazione di funzione .

La domanda aveva quasi certamente lo scopo di porre la domanda "vero o falso: l'ultimo token in una dichiarazione di funzione è sempre un punto e virgola" Ma non è questa la domanda che hanno scritto, perché l'autore del quiz non stava pensando chiaramente al problema.

Il mio consiglio è di evitare del tutto i quiz sul linguaggio di programmazione. Sono abbastanza orribili.


Curiosità, mentre siamo sull'argomento. In C #, questi sono tutti legali:

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

In C #, una dichiarazione di classe o di struttura può terminare con un punto e virgola o no, a tua discrezione. Questa strana piccola funzionalità è stata aggiunta a vantaggio dei programmatori C / C ++ che arrivano a C # e ne hanno a portata di mano le dichiarazioni di tipo che terminano con un punto e virgola inutile; il team di progettazione non ha voluto punirli per avere questa abitudine. :-)


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Samuel Liew

25

Puoi dichiarare anche una funzione come questa:

int func(){
    return 1;
}

La dichiarazione è molto ambigua. La risposta giusta dovrebbe essere: dipende da come dichiarate la funzione.

Ad ogni modo, avrei scelto anche falso e forse potresti segnalare la domanda a qualcuno.


3
Comunque, non mettere la cosa a livello personale. L'importante è che tu abbia capito come funziona una definizione di dichiarazione di funzione, quindi non preoccuparti troppo, assicurati solo che la domanda sia almeno verificata e continua
Luca Corsini,

11
Assolutamente. Onestamente, ho imparato di più sulla definizione della dichiarazione di funzione dall'errare la domanda di quanto non avrei fatto se fosse stata corretta.
Logan,

1
@Logan non ti preoccupare troppo. Se sai come scrivere e leggere una funzione che è tutto ciò di cui hai bisogno. Personalmente odio questo tipo di domande che 1. non sono ben definite 2. testa la tua conoscenza teorica della sintassi. Per me è come la memoria muscolare. Quando scrivo ogni cifra va senza sforzo alla chiave che dovrebbe andare, ma se mi dai un test su quali tasti dovrebbe premere una cifra sarei completamente senza speranza senza una tastiera per fare fisicamente l'azione ...
Bolov

2
... Scrivere una sintassi comune (ad es. Come una funzione) diventerà una seconda natura per te. E quando sbaglierai perché hai appena cambiato lingua, beh ... l'evidenziazione di intellisense e sintassi rende soluzioni rapide ed efficienti. Investi il ​​tuo tempo ed energia in qualcosa di più utile.
Bolov,

20

Un punto e virgola (';') non è necessario dopo una dichiarazione di funzione.

Vero o falso.

Vero . Un punto e virgola non è necessario dopo alcuna dichiarazione. Né dopo alcuna definizione. Né dopo alcuna affermazione.

Molti tipi di dichiarazione devono terminare con un punto e virgola, come specifica la sintassi nella sezione 7 [dcl.dcl]. Ma non c'è mai bisogno di scriverne una dopo.


1
Vedo che Eric Lippert ha già discusso di questo punto. Immagino che tutti i voti mi abbiano fatto trascurare. Sentiti libero di esprimere il tuo voto lì.
Marc van Leeuwen,

Praticamente qualsiasi domanda che ponga: "X è sempre vera: vera o falsa?" avrà la risposta "falso". Diamine, non c'è bisogno di avere un punto e virgola ovunque ; il compilatore potrebbe lamentarsi e rifiutarsi di compilare il programma, ma non è certo la fine del mondo; Non lo definirei un bisogno fondamentale . ;)
Quuxplusone,

@Quuxplusone se il compilatore rifiuta il tuo programma, il tuo programma non contiene dichiarazioni di funzioni :)
Ben Millwood,

6

Questo dipende dal fatto che stiamo dichiarando o definendo la funzione. Se dichiariamo la funzione, dobbiamo includere il punto ;e virgola ( ) e se stiamo definendo la funzione, il punto e virgola non è necessario.

Una dichiarazione è così:

int add(int, int);

E una definizione è così:

int add(int a, int b)
{
    // ...
}

10
Il problema con questa risposta è che suggerisce che le definizioni e le dichiarazioni si escludono a vicenda. In effetti, ogni definizione è una dichiarazione; le definizioni sono un sottoinsieme di dichiarazioni.
Salteri il

6

Anche se sono d'accordo con quasi tutte le altre risposte, affermando che la domanda è formulata in modo molto ambiguo e che la tua risposta è tecnicamente corretta, permettimi di dare una prospettiva diversa:

Ecco come li ho sempre chiamati:

void func();  // The function prototype

...

void func()
{
    // The function definition
}

Suppongo che la domanda sia stata inventata tenendo presente questa terminologia.

Definizione e dichiarazione sono entrambe lo stesso concetto ai miei occhi. "Definisco x = y" == "Dichiaro x = y".

Ma ovviamente, c'è una grande differenza tra il prototipo di funzione (in alto) e la definizione effettiva della funzione.


Per me il tuo prototipo è la dichiarazione basata su come ho appreso (non dicendo che hai torto comunque), ma poi mi aspetterei anche un prototipo che specifichi il numero e il tipo di argomenti, o nulla, ma mi aspetto che tu abbia omesso per brevità.
David S,

David S: Sì, ovviamente conterrebbe anche il numero e il tipo di argomenti, ma in effetti li ho omessi per brevità (nota che non ci sono argomenti nella dichiarazione di funzione effettiva). Tuttavia, non sono davvero d'accordo quando dici che la dichiarazione di piena funzione si chiama prototipo. Cito Wikipedia: "un prototipo di funzione o un'interfaccia di funzione è una dichiarazione di una funzione che specifica il nome della funzione e la firma del tipo (arity, tipi di dati dei parametri e tipo restituito), ma omette il corpo della funzione".
Opifex,

@DavidS: in C ++, le dichiarazioni di funzioni sono sempre prototipi (o definizioni), ed void func();è esattamente equivalente a void func(void);. Questo è molto diverso da C , dove void func();non dice al compilatore nulla degli arg e non è la stessa cosa di void func(void);. Un prototipo o una definizione successivi sono una buona idea, altrimenti il ​​chiamante deve applicare le promozioni arg predefinite (es. Float -> double e tipi interi stretti a int. Stesse regole di args per le funzioni variadiche).
Peter Cordes

Mi scuso, sono finito qui guardando qualcosa in relazione al C e non ho notato il cambio di lingua. Non eliminerò il mio commento a fini di chiarezza, ma lo considero ritirato.
David S,

6

È un peccato che la domanda che hai fatto non dica "subito dopo". Potremmo ad esempio scrivere questo:

int func()  /* My function */ ;

Oppure potrei scrivere:

int func()
int a = 42;

Nel primo caso il punto e virgola non è direttamente dopo la dichiarazione, ma sarebbe OK.

Nel secondo caso c'è un punto e virgola "dopo" la dichiarazione, ma non direttamente dopo.

Penso che Eric Lippert abbia la giusta idea nella sua risposta .

È come dire "dovrebbe esserci un periodo dopo la fine di una frase in inglese?". Probabilmente, una frase ha già un punto alla fine (altrimenti non sarebbe una frase) e quindi non dovrebbe esserci un periodo dopo la frase.


4
Bello. Termina quella frase con un periodo in più. Vedo quello che hai fatto là.
David S,

2
int func() int a=42;non compilare. Hai bisogno di una virgola, non di un'altra int. Vedi la risposta di @ Arne pubblicata più di un giorno prima. L'unica novità di questa risposta è l'ultimo paragrafo, con l'analogia con le frasi inglesi.
Peter Cordes,

1
Non ho detto il secondo esempio compilato. Stavo sottolineando che dicendo che era necessario un punto e virgola "dopo" la dichiarazione era ambigua. Il mio esempio aveva un punto e virgola dopo la dichiarazione ma non viene compilato.
Nick Gammon,

1
Lo stesso problema si verifica nei messaggi di errore; un esempio preferito da C # è " parametro A params deve essere l'ultimo parametro in un elenco di parametri formali ". Supponiamo invece che io abbia detto "Un frob deve essere l'ultimo guaio in un elenco di gloob". Significa questo (1) Ogni elenco gloob ha esattamente un palmo alla fine, come ogni domanda ha esattamente un punto interrogativo alla fine, (2) Un elenco gloob può avere un numero qualsiasi di frob, ma se ha uno o più frob , l'ultimo elemento deve essere un capovolgimento, come un numero pari può avere qualsiasi numero di 02468, ma uno dei deve essere l'ultimo, oppure ...
Eric Lippert,

... (3) un elenco gloob può avere zero o uno frob, e se ne ha uno, arriva alla fine? Se non conosci il contesto, penso che (1) sia la spiegazione più sensata, ma nel caso di "parametro params", (3) è la spiegazione corretta. Molte descrizioni informali degli elementi del linguaggio di programmazione hanno una proprietà che i miei amici del redattore tecnico chiamano "COIK" - Cancella solo se noto. Se non capisci già a fondo il materiale, una sua descrizione è inutile per te, ma se lo capisci già a fondo, non ti serve la descrizione!
Eric Lippert,

4

È possibile utilizzare ;solo per prototipi.


4

È una domanda un po 'complicata, ma hanno usato la parola dichiarazione che significa qualcosa del genere:

int example();

Quindi è vero in questo caso.

Se avessero usato la parola implementazione , sarebbe stato falso.


2

Il punto e virgola (;) viene utilizzato per indicare al compilatore che dopo questo punto e virgola (;) inizia una nuova istruzione.

Quindi penso che il punto e virgola (;) sia richiesto solo durante una dichiarazione di funzione. Quindi, secondo me, la risposta sarà vera.


Le dichiarazioni non sono tuttavia dichiarazioni.
HolyBlackCat

ma dopo la dichiarazione di funzione, stiamo eseguendo una nuova riga di codice usando il compilatore. quindi penso che prima di eseguire una nuova riga di compilatore di codice sappia dove finisce la precedente riga di codice, quindi un compilatore può generare codice nativo (ovvero 0101).
Jatinder,

2

Quando le funzioni sono definite prima di main () :

  • Non è necessario il punto e virgola perché la funzione è già definita

Quando le funzioni sono definite dopo main () :

  • Hai bisogno del punto e virgola perché perché stai prototipando quella funzione e stai dicendo al compilatore che la funzione esce.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.