Un point-virgule (';') n'est-il pas nécessaire après une déclaration de fonction en C ++?

174

Je viens de passer un test de programmation intermédiaire, et l'une des questions que je me suis trompé était la suivante:

Un point-virgule (';') n'est pas nécessaire après une déclaration de fonction.

Vrai ou faux.

J'ai choisi "faux" (et corrigez-moi si je me trompe car j'ai l'impression de devenir fou), une déclaration de fonction est ce que vous écrivez avant la définition (en haut du code) pour que le compilateur connaisse la fonction appelez avant même de l'appeler, et une définition de fonction est ce qui constitue la fonction dans son ensemble.

C'est à dire,

Déclaration:

int func();

Définition:

int func() {
  return 1;
}

La réponse à cela ne devrait-elle pas être fausse?

Logan
la source
41
Une définition est aussi une déclaration. Mais je dirais que votre réponse était correcte.
216
C'est une question délicate et n'a aucune incidence sur la capacité de quiconque à bien programmer.
phonetagger
40
Je trouve toujours les questions, qui aboutissent à des doubles négatifs, déroutantes. Dans mon esprit, ces questions sont conçues pour tromper les étudiants. Pourquoi la question n'a-t-elle pas pu être formée de la manière suivante: "Un point-virgule (';') est toujours nécessaire après une déclaration de fonction. Vrai ou Faux."? : /
Algirdas Preidžius
18
@phonetagger Toute cette confusion montre à quel point la question est mal formulée.
François Andrieux
34
Le rasoir de Hanlon suggère que l'auteur du test a confondu «déclaration» et «définition».
Sneftel

Réponses:

161

Vous pouvez avoir une situation où vous déclarez et définissez la fonction en une seule étape, c'est-à-dire si vous incluez la définition de fonction au point où vous la déclarez. Donc, techniquement, je suppose que la vérité est correcte. Mais la question est formulée de telle manière que j'y aurais répondu comme vous l'avez fait.

jwismar
la source
10
Je dirais que vrai n'est pas correct à cause de la raison que vous avez donnée. S'il y a des cas où un point-virgule est nécessaire, alors il est faux (ou faux). Le vrai est pour moi l'absolu, s'il y a des cas évidents où cela est nécessaire, vous ne pouvez pas dire vrai.
I Funball
16
@IFunball Bon argument. Langues natives stupides. La phrase "Un point-virgule (';') n'est pas nécessaire après une déclaration de fonction" peut être lue comme "Un point-virgule (';') n'est (jamais) nécessaire après une déclaration de fonction" ou comme "Un point-virgule (';' ) n'est pas (toujours) nécessaire après une déclaration de fonction ". La qualification de l'énoncé comme vraie ou fausse dépend du choix d'une interprétation. À proprement parler, la question n'est pas claire et n'a donc pas de réponse claire.
Peter - Réintègre Monica le
6
@IFunball C'est parce que "déclaration", sans autre contexte et sans déclaration que nous sommes des juristes en matière de langage, est généralement comprise comme signifiant "une déclaration non-définissant". La question était injuste.
Courses de légèreté en orbite le
2
Toute question d'examen qui n'est pas claire pour quelqu'un qui connaît le contenu testé fait l'objet d'un bug.
Nat
2
On dirait que nous devons ajouter une clause de comportement non définie à la langue anglaise
Nick Mertin
147

En plus de la chose "une définition est aussi une déclaration", ce qui suit est un C ++ légal:

int f(), g();

Cela déclare deux fonctions, fet g, toutes deux sans arguments et avec un type de retour de int, mais la définition de fn'est pas suivie (immédiatement) d'un point-virgule. De même, c'est légal:

int f(), i = 42;

Mais il n'est en effet pas permis d'omettre complètement le point-virgule dans ces cas, il serait donc quelque peu surprenant que l'un ou l'autre soit pris comme exemple de déclaration sans point-virgule suivant. En fait, ce qui suit est illégal:

void *p, f() {}

Hormis une (simple) déclaration de fonction, une définition de fonction ne peut être combinée avec aucune autre déclaration ou définition pour le même spécificateur de type . (Si cela était légal, cela définirait à la fois a void *pet a void f() {}.)

Dans tous les cas, cela semble être une question de type "gotcha" qui ne devrait pas être dans un test de programmation intermédiaire.

(Oh, au fait, n'écrivez pas de code comme ça int f(), i = 42;.)

Arne Vogel
la source
2
Il est également possible d'utiliser un typedef pour définir un type de fonction, puis de l'utiliser pour déclarer plusieurs fonctions à la fois, par exemple, typedef int fooProc(int); fooProc a,b.c.d.e;je ne sais pas pourquoi les en-têtes standard des compilateurs basés sur un lecteur de disquette ne l'ont pas fait dans le jour, car je pense que cela aurait permis aux fichiers d'en-tête d'être beaucoup plus petits et donc plus rapides à traiter.
supercat
Considérez également int f(int(&g)(),int(*h)()){return g()+h();}ceci a trois déclarations de fonction, dont l'une est suivie d'une accolade ouverte, une autre par une virgule et une troisième par une parenthèse fermée.
David Hammen
1
@DavidHammen: Cela ne déclare pas strictement les fonctions autres que int f(stuff). Même dans la portée de la fonction, gest une variable automatique de type référence à la fonction et hest un pointeur vers la fonction .
Peter Cordes
83

Les autres réponses et commentaires évoquent plusieurs des nombreuses façons dont il s'agit d'une question horrible, trompeuse et mal écrite. Mais il y a un autre problème que personne d'autre n'a encore identifié. La question est:

Un point-virgule (';') n'est pas nécessaire après une déclaration de fonction. Vrai ou faux.

OK, regardons une déclaration de fonction:

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

Tout cela est la déclaration . La déclaration ne int func()puis suivie d' un ;. La déclaration est int func();suivie d'un espace blanc.

Donc, la question est: un point-virgule est-il nécessaire après la déclaration ? Bien sûr que non. La déclaration contient déjà un point-virgule qui l'a terminée. Un point-virgule après la déclaration serait inutile. En revanche, int func(); ;serait un point-virgule après une déclaration de fonction .

La question visait presque certainement à poser la question "vrai ou faux: le dernier jeton dans une déclaration de fonction est toujours un point-virgule" Mais ce n'est pas la question qu'ils ont écrite, car l'auteur du quiz ne pensait pas clairement au problème.

Mon conseil est d'éviter complètement les quiz de langage de programmation. Ils sont assez horribles.


Fait amusant, pendant que nous sommes sur le sujet. En C #, tout cela est légal:

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

En C #, une déclaration de classe ou de structure peut se terminer par un point-virgule, ou non, à votre discrétion. Cette petite fonctionnalité étrange a été ajoutée au profit des programmeurs C / C ++ venant en C # qui ont entre les doigts que les déclarations de type se terminent par un point-virgule inutile; l'équipe de conception ne voulait pas les punir d'avoir cette habitude. :-)

Eric Lippert
la source
Les commentaires ne sont pas destinés à une discussion approfondie; cette conversation a été déplacée vers le chat .
Samuel Liew
25

Vous pouvez également déclarer une fonction comme celle-ci:

int func(){
    return 1;
}

La déclaration est très ambiguë. La bonne réponse devrait être: cela dépend de la façon dont vous déclarez la fonction.

Quoi qu'il en soit, j'aurais choisi faux aussi, et peut-être pourriez-vous signaler la question à quelqu'un.

Luca Corsini
la source
3
Quoi qu'il en soit, ne mettez pas la chose à un niveau personnel. L'important est que vous ayez compris comment fonctionne une définition de déclaration de fonction, alors ne vous inquiétez pas trop, assurez-vous simplement que la question sera au moins vérifiée et continuez
Luca Corsini
11
Absolument. Honnêtement, j'ai appris plus sur la définition de la déclaration de fonction en me trompant sur la question que je ne l'aurais fait correctement.
Logan
1
@Logan ne vous inquiétez pas trop. Si vous savez écrire et lire une fonction, c'est tout ce dont vous avez besoin. Personnellement, je déteste ce genre de questions qui 1. ne sont pas bien définies 2. testez vos connaissances théoriques de la syntaxe. Pour moi, c'est comme la mémoire musculaire. Quand j'écris, chaque chiffre va sans effort à la touche, il est censé aller, mais si vous me donnez un test sur les touches qu'un chiffre doit appuyer, je serais complètement désespéré sans clavier pour faire physiquement l'action ...
bolov
2
… L'écriture d'une syntaxe commune (par exemple, comme une fonction) deviendra une seconde nature pour vous. Et quand vous allez tout gâcher parce que vous venez de changer de langue, eh bien ... l'intellisense et la coloration syntaxique constituent des solutions rapides et efficaces. Investissez votre temps et votre énergie dans quelque chose de plus utile.
bolov
20

Un point-virgule (';') n'est pas nécessaire après une déclaration de fonction.

Vrai ou faux.

Vrai . Un point-virgule n'est pas nécessaire après une déclaration. Ni après aucune définition. Ni après aucune déclaration.

De nombreux types de déclaration doivent se terminer par un point-virgule, comme le spécifie la syntaxe de la section 7 [dcl.dcl]. Mais il n'est jamais nécessaire d'en écrire un second après cela.

Marc van Leeuwen
la source
1
Je vois qu'Eric Lippert a déjà fait valoir ce point. Je suppose que tous les votes positifs m'ont fait oublier. N'hésitez pas à y voter.
Marc van Leeuwen
À peu près n'importe quelle question qui demande, "X est toujours vrai: vrai ou faux?" va avoir la réponse «faux». Heck, il n'est pas nécessaire d'avoir un point-virgule n'importe où ; le compilateur peut se plaindre et refuser de compiler votre programme, mais ce n'est pas la fin du monde; Je n'appellerais pas cela un besoin fondamental . ;)
Quuxplusone
@Quuxplusone si le compilateur rejette votre programme, votre programme ne contient aucune déclaration de fonction :)
Ben Millwood
6

Cela dépend si nous déclarons ou définissons la fonction. Si nous déclarons la fonction, nous devons inclure le point-virgule ( ;), et si nous définissons la fonction, le point-virgule n'est pas nécessaire.

Une déclaration est comme ceci:

int add(int, int);

Et une définition est comme ceci:

int add(int a, int b)
{
    // ...
}
Rocx En Ruff
la source
10
Le problème avec cette réponse est qu'elle suggère que les définitions et la déclaration s'excluent mutuellement. En fait, chaque définition est une déclaration; les définitions sont un sous-ensemble de déclarations.
MSalters
6

Même si je suis d'accord avec presque toutes les autres réponses, en déclarant que la question est formulée de manière très ambiguë et que votre réponse est techniquement correcte, permettez-moi de donner une perspective différente:

C'est ainsi que je les ai toujours appelés:

void func();  // The function prototype

...

void func()
{
    // The function definition
}

Je suppose que la question a été posée avec cette terminologie à l'esprit.

La définition et la déclaration sont toutes deux le même concept à mes yeux. "Je définis x = y" == "Je déclare x = y".

Mais bien sûr, il y a une grande différence entre le prototype de fonction (en haut) et la définition réelle de la fonction.

Opifex
la source
Pour moi, votre prototype est la déclaration basée sur la façon dont j'ai appris (sans dire que vous vous trompez non plus), mais je m'attendrais également à ce qu'un prototype spécifie le nombre et le type d'arguments, ou nul, mais je suppose que vous avez omis cela par souci de brièveté.
David S
David S: Oui, bien sûr, il contiendrait également le nombre et le type d'arguments, mais je les ai en effet omis par souci de concision (notez qu'il n'y a pas non plus d'arguments dans la déclaration de fonction réelle). Cependant, je ne suis pas vraiment d'accord lorsque vous dites que la déclaration de fonction complète s'appelle le prototype. Je cite Wikipedia: "un prototype de fonction ou une interface de fonction est une déclaration d'une fonction qui spécifie le nom et la signature de type de la fonction (arité, types de données des paramètres et type de retour), mais omet le corps de la fonction."
Opifex
@DavidS: En C ++, les déclarations de fonctions sont toujours des prototypes (ou définitions), et void func();sont exactement équivalentes à void func(void);. C'est très différent de C , où void func();ne dit rien au compilateur sur les arguments, et ce n'est pas la même chose que void func(void);. Un prototype ou une définition plus tardive est une bonne idée, sinon l'appelant doit appliquer les promotions arg par défaut (par exemple, float -> double, et les types entiers étroits à int. Mêmes règles que pour args aux fonctions variadiques.)
Peter Cordes
Mes excuses, j'ai fini par regarder quelque chose de C lié et je n'ai pas noté le changement de langue. Je ne supprimerai pas mon commentaire dans un souci de clarté, mais je le considère comme retiré.
David S
6

C'est dommage que la question que vous avez posée ne dise pas «directement après». On pourrait par exemple écrire ceci:

int func()  /* My function */ ;

Ou je pourrais écrire:

int func()
int a = 42;

Dans le premier cas, le point-virgule n'est pas directement après la déclaration, mais ce serait OK.

Dans le second cas, il y a un point-virgule "après" la déclaration, mais pas directement après.

Je pense qu'Eric Lippert a la bonne idée dans sa réponse .

C'est comme dire "devrait-il y avoir un point après la fin d'une phrase en anglais?". On peut soutenir qu'une phrase a déjà un point à la fin (sinon ce ne serait pas une phrase) et qu'il ne devrait donc pas y avoir de point après la phrase.

Nick Gammon
la source
4
Agréable. Mettre fin à cette phrase par un délai supplémentaire. Je vois ce que tu as fait là.
David S
2
int func() int a=42;ne compile pas. Vous avez besoin d'une virgule, pas d'une autre int. Voir la réponse de @ Arne publiée plus d'un jour avant cela. La seule nouveauté dans cette réponse est le dernier paragraphe, avec l'analogie avec les phrases anglaises.
Peter Cordes
1
Je n'ai pas dit que le deuxième exemple était compilé. Je faisais remarquer que dire qu'un point-virgule était nécessaire «après» la déclaration était ambigu. Mon exemple avait un point-virgule après la déclaration mais il ne compile pas .
Nick Gammon
1
Ce même problème se produit dans les messages d'erreur; un exemple favori de C # est " Un paramètre params doit être le dernier paramètre dans une liste de paramètres formelle ". Maintenant, supposons qu'à la place je dise "Un frob doit être le dernier gloob dans une liste gloob". Cela signifie-t-il que (1) Chaque liste gloob a exactement une frob à la fin, comme chaque question a exactement un point d'interrogation à la fin, (2) Une liste gloob peut avoir n'importe quel nombre de frob, mais si elle a une ou plusieurs frob , le dernier élément doit être une frob, comme un nombre pair peut avoir n'importe quel nombre de 02468, mais l'un des doit être le dernier, ou ...
Eric Lippert
... (3) une liste gloob peut avoir zéro ou une frobs, et si elle en a une, elle vient à la fin? Si vous ne connaissez pas le contexte, je pense que (1) est l'explication la plus sensée, mais dans le cas du "paramètre params", (3) est l'explication correcte. De nombreuses descriptions informelles des éléments du langage de programmation ont une propriété que mes amis rédacteurs techniques appellent "COIK" - Clear Only If Known. Si vous ne comprenez pas déjà complètement le matériel, une description de celui-ci vous est inutile, mais si vous le comprenez déjà complètement, vous n'avez pas besoin de la description!
Eric Lippert
4

Vous ne pouvez utiliser que ;pour les prototypes.

M7off
la source
4

C'est un peu une question délicate, mais ils ont utilisé le mot déclaration qui signifie quelque chose comme ceci:

int example();

C'est donc vrai dans ce cas.

S'ils avaient utilisé le mot implémentation, c'était faux.

dark_3nergy
la source
2

Le point-virgule (;) est utilisé pour indiquer au compilateur qu'après ce point-virgule (;) une nouvelle instruction démarre.

Je pense donc que le point-virgule (;) n'est requis que lors d'une déclaration de fonction. Donc, selon moi, la réponse sera vraie.

Jatinder
la source
Les déclarations ne sont cependant pas des déclarations.
HolyBlackCat
mais après la déclaration de la fonction, nous exécutons une nouvelle ligne de code en utilisant le compilateur. donc je pense qu'avant d'exécuter une nouvelle ligne de code, le compilateur doit savoir où se termine la ligne de code précédente seulement alors un compilateur peut générer du code natif (c'est-à-dire 0101).
Jatinder
2

Lorsque les fonctions sont définies avant main () :

  • Pas besoin de point - virgule car la fonction est déjà définie

Lorsque les fonctions sont définies après main () :

  • Besoin d'un point - virgule parce que vous créez un prototypage de cette fonction et que vous dites au compilateur que la fonction se termine.
shiv shah
la source