37 votes

Comment le compilateur sait-il que la virgule dans un appel de fonction n'est pas un opérateur de virgule?

Considérez l'appel de fonction (appelant int sum(int, int) )

 printf("%d", sum(a,b));
 

Comment le compilateur décide-t-il que le , utilisé dans l'appel de fonction sum(int, int) n'est pas un opérateur de virgule?

REMARQUE : je ne voulais pas utiliser réellement l'opérateur virgule dans l'appel de fonction. Je voulais juste savoir comment le compilateur sait que ce n'est pas un opérateur de virgule.

49voto

ams Points 10312

Regardez la grammaire pour le langage C. Il a énuméré, dans son intégralité, dans l'Annexe A de la norme. La façon dont cela fonctionne est que vous pouvez parcourir chaque jeton dans un programme C et de les relier à l'élément suivant dans la grammaire. À chaque étape, vous avez seulement un nombre limité d'options, de sorte que l'interprétation d'un personnage donné dépendra du contexte dans lequel il apparaît. À l'intérieur de chaque règle de la grammaire, chaque ligne donne une alternative valable pour le programme de match.

Plus précisément, si vous recherchez parameter-list, vous verrez qu'il contient explicite d'une virgule. Par conséquent, chaque fois que le compilateur C de l'analyseur est dans "paramètres-liste" mode, des virgules qu'il trouve seront considérés comme des séparateurs de paramètre, non pas comme des virgules opérateurs. Le même est vrai pour les crochets (qui peut également se produire dans des expressions).

Cela fonctionne parce que l' parameter-list règle est prudent d'utiliser assignment-expression règles, plutôt que de simplement la plaine expression règle. Un expression peut contenir des virgules, alors qu'un assignment-expression ne le peuvent pas. Si ce n'était pas le cas de la grammaire d'être ambigu, et le compilateur ne sais pas quoi faire quand il a rencontré une virgule à l'intérieur d'une liste de paramètres.

Cependant, un crochet ouvrant, par exemple, qui n'est pas partie de la définition d'une fonction/d'appel, ou un if, whileou for déclaration, sera interprétée comme une partie d'une expression (car il n'y a pas d'autre option, mais seulement si le début d'une expression est un choix valide à ce point), puis, entre parenthèses, le expression règles de syntaxe s'applique, et qui permet à virgule opérateurs.

26voto

Yu Hao Points 40603

De C99 6.5.17:

Comme indiqué par la syntaxe, l'opérateur virgule (comme décrit dans le présent sous-alinéa) ne peut pas apparaissent dans des contextes où une virgule est utilisée pour séparer des éléments dans une liste (comme arguments des fonctions ou des listes des initialiseurs). D'autre part, il peut être utilisé à l'intérieur d'une mise entre parenthèses de l'expression ou de l'intérieur de la deuxième l'expression d'un opérateur conditionnel dans de tels contextes. Dans l'appel de fonction

f(a, (t=3, t+2), c)

la fonction a trois arguments, le second de qui a la valeur 5.

Un autre exemple similaire est l'initialiseur liste des tableaux ou des structures:

int array[5] = {1, 2};
struct Foo bar = {1, 2};

Si un opérateur virgule devaient être utilisée comme paramètre de la fonction, de l'utiliser comme ceci:

sum((a,b))

Ce ne compile pas, bien sûr.

19voto

Jens Points 17702

La raison est que le C de la Grammaire. Alors que tout le monde semble l'aimer pour citer un exemple, la vraie affaire, c'est l'expression de la structure de la grammaire pour les appels de fonction dans la Norme (C99). Oui, l'appel de la fonction se compose de l' () opérateur appliqué à un postfix expression (comme par exemple un identifiant):

 6.5.2 postfix-expression:
       ...
       postfix-expression ( argument-expression-list_opt )

avec

argument-expression-list:
       assignment-expression
       argument-expression-list , assignment-expression    <-- arglist comma

expression:
       assignment-expression
       expression , assignment-expression                  <-- comma operator

L'opérateur virgule ne peut se produire dans une expression, c'est à dire plus bas, dans la dans la grammaire. Ainsi, le compilateur traite d'une virgule dans une fonction de la liste d'arguments comme celui séparant l'affectation des expressions, ce n'est pas en séparant les expressions.

11voto

Roddy Points 32503

Les réponses existantes dire "parce que le langage C spec dit que c'est un séparateur de liste, et non pas un opérateur".

Cependant, votre question est de se demander "comment le compilateur de savoir...", et c'est tout à fait différent: C'est vraiment pas différent de la façon dont le compilateur sait que la virgule en printf("Hello, world\n"); n'est pas un opérateur virgule: Le compilateur sait parce que le contexte dans lequel la virgule apparaît - au fond, ce qui est passé avant.

C 'langue' peut être décrite en Forme de Backus Naur (BNF) - pour l'essentiel, un ensemble de règles que le compilateur de l' analyseur utilise pour analyser votre fichier d'entrée. La BNF pour C wil faire la distinction entre ces différentes occurrences de virgules dans la langue.

Il y a beaucoup de bonnes ressources sur la façon dont les compilateurs de travail, et la façon d'en écrire un.

6voto

unwind Points 181987

Le projet de standard C99 dit:

Comme indiqué par la syntaxe, l'opérateur virgule (comme décrit dans le présent sous-alinéa) ne peut pas apparaissent dans des contextes où une virgule est utilisée pour séparer des éléments dans une liste (comme arguments des fonctions ou des listes de initialiseurs). D'autre part, il peut être utilisé à l'intérieur d'une mise entre parenthèses de l'expression ou de l'intérieur de la deuxième expression d'un opérateur conditionnel dans de tels contextes. Dans l'appel de fonction f(a, (t=3, t+2), c) la fonction a trois arguments, le second de qui a la valeur 5.

En d'autres termes, "parce que".

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