0

Après avoir lu les deux suivantes ...Quelle est l'expression compliquée utilisant l'opérateur de virgule analysé dans C?

What does the comma operator , do?

How does the Comma Operator work

Je ne suis toujours pas sûr que je ne peux pas analyser la déclaration suivante que j'ai trouvé dans quelqu'un le code source d'un autre:

int i, n, val, locala = a, bestval = -INFINITY; 

L'opérateur de virgule est évalué dans l'ordre de gauche à droite, oui? Si nous utilisons entre parenthèses pour montrer l'ordre de préséance, je pense que nous avons quelque chose comme ceci: Alors

(int i, (n, (val, (locala = a, (bestval = -INFINITY))))); 

, le est d'origine peut-être équivalent à ce qui suit?

int bestval = -INFINITY; 
int locala = a; 
int val; 
int n; 
int i; 

Si oui, pourquoi le mot-clé int appliqué à toutes les variables au lieu de seulement la plus à gauche variables i?

De même, les expressions les plus à droite retournent leur valeur, oui? Par conséquent, locala = a peut renvoyer la valeur locala après l'affectation. Cela signifie-t-il que les variables i, n et val sont toutes initialisées? Si oui, à quoi sont-ils initialisés? -INFINITY? la valeur de a?

+6

Ce n'est pas l'opérateur de virgule. La plupart des utilisations de virgules dans C ne sont pas l'opérateur de virgule. – user2357112

+0

Règle empirique: si la chose à gauche n'est pas défaussée, ce n'est pas l'opérateur virgule. – user2357112

+1

@Toothpick Anemone Il n'y a pas d'opérateur virgule. Il y a une liste de déclaration. –

Répondre

4

Ce

int i, n, val, locala = a, bestval = -INFINITY; 

est une déclaration.

La déclaration est définie de la manière suivante en C (sans tous les détails)

declaration: 
    declaration-specifiers init-declarator-listopt ; 

init-declarator-list: 
    init-declarator 
    init-declarator-list , init-declarator 

init-declarator: 
    declarator 
    declarator = initializer 

La déclaration spécificateurs affecte tous déclarateurs dans la init-declarator- liste.

Si vous souhaitez utiliser l'opérateur virgule dans une déclaration alors une telle déclaration peut par exemple chercher comme

int i = 1, j = 2, k = (++i, j++, i + j); 

Ici l'expression (++i, j++, i + j) utilisé comme un initialiseur basé sur l'opérateur virgule.

Après la déclaration i est égale à 2, j-3 et k-5.

3

Le jeton virgule fait plusieurs choses différentes en C, qui ne devrait pas être confondus:

  • Sépare les paramètres d'une définition de macro préprocesseur fonction comme:

    #define CAT_NO_EXPAND(x,y) x ## y 
    
  • Sépare les arguments d'une macro de préprocesseur de type fonction utiliser:

    int CAT_NO_EXPAND(ident_, 3) = 3; 
    
  • sépare les enquêteurs dans une définition d'enum:

    enum colors { RED, GREEN, BLUE }; 
    
  • sépare les déclarateurs dans une déclaration:

    int a, b=3, c; 
    
  • sépare les membres/éléments dans un initialiseur contreventé:

    int arr[3] = {0, 2, 4}; 
    struct mystruct s = {8, 3.0}; 
    func((mystruct s){8, 3.0}); 
    
  • Sépare les paramètres d'une déclaration ou d'une définition de fonction:

    void f(int n, double, const char* fmt, ...); 
    
  • sépare les arguments d'une expression d'appel de fonction:

    f(3, 0.5, "Test %s\n", "Hello"); 
    
  • formes d'expression qui s'évalué rejettera le côté gauche et utiliser la valeur du côté droit comme valeur.

    #define CALL_G_IGNORE_RESULT(x) ((void)g(x), 0) 
    for (i=0, j=0; i<m && j<n; ++i, ++j) 
    

Qu'est-ce que vous avez lu sur le « opérateur virgule » est seulement décrivant le dernier cas, qui travaille dans un contexte d'expression qui ne correspond à aucun des autres cas ci-dessus.

Ce que vous avez posté est une déclaration, qui n'implique pas l '"opérateur de virgule" et déclare simplement plusieurs variables à la fois. Tous les initialiseurs sont évalués dans l'ordre (ce qui est important car vous pouvez utiliser une variable déclarée plus tôt dans un initialiseur ultérieur).

+0

vous pouvez mettre en retrait les blocs de code par 4 autres espaces à l'intérieur des éléments de la liste pour rendre cette apparence plus agréable –

+0

@AnttiHaapala Je le ferais d'habitude, mais SO semble avoir des problèmes avec le code immédiatement après un élément de liste de balle. – aschepler

+0

Les espaces sont comme la violence, s'ils ne fonctionnent pas, vous n'utilisez pas assez. –

0
  1. Ceci n'est pas l'opérateur de virgule.
  2. C'est une liste de déclaration.
  3. Il est exécuté de gauche à droite, ou au moins ses parties exécutables le sont.
  4. L'ordre d'évaluation et la priorité de l'opérateur sont deux choses différentes.
  5. L'ordre d'exécution de gauche à droite est l'opposé de ce que vous avez affiché entre parenthèses.
  6. Le mot clé int est appliqué à toutes les déclarations car c'est ce que signifie la syntaxe.
  7. Ici, il n'y a pas d'expressions 'right-most', seulement des déclarations avec des initialiseurs.
  8. Il n'y a donc pas de valeurs retournées non plus.
  9. i, n et val ne sont pas initialisés.