470 votes

Expression versus déclaration

Je pose la question en ce qui concerne le langage C#, mais je suppose que c'est la même chose dans la plupart des autres langages.

Quelqu'un a-t-il une bonne définition de expressions et déclarations et quelles sont les différences ?

4 votes

Je trouve que la réponse que vous avez choisie est ambiguë. Une expression fait également quelque chose - elle est évaluée à une valeur. J'ai fourni une réponse non ambiguë.

4 votes

@ShelbyMooreIII - Non-ambiguë et aussi fausse. La réponse acceptée est formulée de manière informelle, mais cette formulation la rend facile à comprendre - et surtout, le sens qu'elle transmet est exact.

0 votes

@JustinMorgan Malheureusement, les définitions de la réponse acceptée sont aussi manifestement erronées ("évalue à une valeur"/"une ligne de code") pour la plupart des langages contemporains, y compris ceux de type C : les expressions peuvent être utilisées dans des contextes non évalués et les déclarations n'ont rien à voir avec les lignes. Même s'il y a quelques explications, la réponse courte est confuse et trompeuse.

568voto

Joel Spolsky Points 22686

Expression : Quelque chose qui est évalué à une valeur. Exemple : 1+2/x
Déclaration : Une ligne de code qui fait quelque chose. Exemple : GOTO 100

Dans les premiers langages de programmation à usage général, comme le FORTRAN, la distinction était claire comme de l'eau de roche. En FORTRAN, une instruction était une unité d'exécution, une chose que vous faisiez. La seule raison pour laquelle elle n'était pas appelée "ligne" était qu'elle s'étendait parfois sur plusieurs lignes. Une expression en soi ne pouvait rien faire... il fallait l'assigner à une variable.

1 + 2 / X

est une erreur en FORTRAN, car elle ne fait rien. Vous deviez faire quelque chose avec cette expression :

X = 1 + 2 / X

FORTRAN n'avait pas de grammaire telle que nous la connaissons aujourd'hui - cette idée a été inventée, avec la forme Backus-Naur (BNF), dans le cadre de la définition d'Algol-60. À ce moment-là, le sémantique distinction ("avoir une valeur" par rapport à "faire quelque chose") a été consacrée par la loi sur la protection de l'environnement. syntaxe Un type de phrase est une expression, un autre est une déclaration, et l'analyseur syntaxique peut les distinguer.

Les concepteurs des langages ultérieurs ont brouillé la distinction : ils ont autorisé les expressions syntaxiques à faire des choses et les déclarations syntaxiques à avoir des valeurs. L'exemple le plus ancien de langage populaire qui subsiste encore est le C. Les concepteurs du C ont compris qu'il n'y avait pas de mal à évaluer une expression et à jeter le résultat. En C, chaque expression syntaxique peut être transformée en une déclaration simplement en ajoutant un point-virgule à la fin :

1 + 2 / x;

est une déclaration totalement légitime, même si absolument rien ne se passera. De même, en C, une expression peut avoir effets secondaires - ça peut changer quelque chose.

1 + 2 / callfunc(12);

parce que callfunc pourrait juste faire quelque chose d'utile.

Dès lors que l'on permet à toute expression d'être une déclaration, on peut tout aussi bien autoriser l'opérateur d'affectation (=) à l'intérieur des expressions. C'est pourquoi C vous permet de faire des choses comme

callfunc(x = 2);

Elle évalue l'expression x = 2 (en attribuant la valeur 2 à x) et la transmet ensuite (le 2) à la fonction callfunc .

Cette confusion entre expressions et déclarations se retrouve dans tous les dérivés du langage C (C, C++, C# et Java), qui comportent toujours des déclarations (comme par ex. while ) mais qui permettent d'utiliser presque n'importe quelle expression comme instruction (en C#, seules les expressions d'affectation, d'appel, d'incrémentation et de décrémentation peuvent être utilisées comme instructions ; voir la réponse de Scott Wisniewski).

Le fait d'avoir deux "catégories syntaxiques" (qui est le nom technique pour désigner le genre de choses que sont les déclarations et les expressions) peut entraîner une duplication des efforts. Par exemple, C a deux formes de conditionnel, la forme d'instruction

if (E) S1; else S2;

et la forme d'expression

E ? E1 : E2

Et parfois les gens veulent une duplication qui n'existe pas : en C standard, par exemple, seule une instruction peut déclarer une nouvelle variable locale - mais cette capacité est suffisamment utile pour que le système de gestion de l'information de l'entreprise soit utilisé. compilateur C de GNU fournit une extension GNU qui permet à une expression de déclarer également une variable locale.

Les concepteurs d'autres langages n'aimaient pas ce genre de duplication, et ils ont compris très tôt que si les expressions peuvent avoir des effets secondaires aussi bien que des valeurs, alors le langage syntaxique La distinction entre les déclarations et les expressions n'est pas si utile que cela, c'est pourquoi elle a été supprimée. Haskell, Icon, Lisp et ML sont tous des langages qui n'ont pas de déclarations syntaxiques - ils n'ont que des expressions. Même la classe structurée de boucles et les formes conditionnelles sont considérées comme des expressions, et elles ont des valeurs, mais pas très intéressantes.

9 votes

Si je ne vous interprète pas mal, vous semblez prétendre que "(setf (third foo) 'goose)" est une expression, et non une déclaration, à la fois parce que c'est Lisp, qui "n'a pas de déclarations", et parce que Lisp a plus d'une décennie de plus que C, qui a été le "premier langage populaire à brouiller les lignes [entre expressions et déclarations]". Pourriez-vous m'expliquer les détails de tout cela ?

2 votes

@Curt Sampson, avez-vous posé cette question séparément ?

5 votes

Si je ne me trompe pas, callfunc(x = 2); passe x a callfunc pas 2 . Si x est un flotteur, callfunc(float) sera appelé, et non callfunc(int) . Et en C++, si vous passez x=y a func y func prend une référence et la modifie, elle modifie x pas y .

40voto

Scott Wisniewski Points 14420

Je voudrais apporter une petite correction à la réponse de Joel ci-dessus.

C# ne permet pas à toutes les expressions d'être utilisées comme des déclarations. En particulier, seules les expressions d'affectation, d'appel, d'incrémentation et de décrémentation peuvent être utilisées comme des instructions.

Par exemple, le compilateur C# signalera le code suivant comme une erreur de syntaxe :

1 + 2 ;

25voto

Mark Harrison Points 77152
  • une expression est tout ce qui produit une valeur : 2 + 2
  • une instruction est l'un des "blocs" de base de l'exécution d'un programme.

Notez qu'en C, "=" est en fait un opérateur, qui fait deux choses :

  • retourne la valeur de la sous-expression de droite.
  • copie la valeur de la sous-expression de droite dans la variable de gauche.

Voici un extrait de la grammaire C de l'ANSI. Vous pouvez voir que le C n'a pas beaucoup de types d'instructions différentes... la majorité des instructions dans un programme sont des instructions d'expression, c'est-à-dire une expression avec un point-virgule à la fin.

statement
    : labeled_statement
    | compound_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    ;

expression_statement
    : ';'
    | expression ';'
    ;

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html

2 votes

Logique erronée sur ce qu'est une déclaration. Un programme déclaratif peut aussi s'exécuter, mais un programme déclaratif n'a pas de déclarations. Une déclaration est et fait "Effets secondaires" c'est-à-dire est impératif. cf. ma réponse .

16voto

Patrick Points 20392

Une expression est quelque chose qui renvoie une valeur, alors qu'une déclaration ne le fait pas.

Par exemple :

1 + 2 * 4 * foo.bar()     //Expression
foo.voidFunc(1);          //Statement

La grande différence entre les deux est que vous pouvez enchaîner des expressions, alors que les déclarations ne peuvent pas être enchaînées.

6 votes

Bien sûr, les déclarations peuvent être enchaînées. {stmt1 ; stmt2 ; stmt3;} est une chaîne, et c'est aussi une déclaration (composée) elle-même.

8 votes

foo.voidFunc(1); est une expression avec une valeur nulle. while y if sont des déclarations.

0 votes

Je suis curieux du non-enchaînement des déclarations. Quelque chose comme "if (x > 1) return ;" serait-il considéré comme un enchaînement de deux instructions ?

8voto

Plutôt que de penser à des déclarations, je pense à des expressions vides, hehe... Oh, j'ai trop bu. :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X