89 votes

Pourquoi n'est-il pas un+++++b en C?

int main ()
{
   int a = 5,b = 2;
   printf("%d",a+++++b);
   return 0;
}

Ce code donne:

erreur: lvalue nécessaire que incrément opérande

Mais si je mets des espaces dans a++ + et ++b, alors qu'elle fonctionne très bien.

int main ()
    {
       int a = 5,b = 2;
       printf("%d",a++ + ++b);
       return 0;
    }

Que signifie l'erreur moyenne dans le premier exemple?

181voto

Lou Franco Points 48823

Les compilateurs sont écrits dans les stades. La première étape est appelée l'analyseur lexical et transforme les caractères dans une symbolique de la structure. Donc, " ++ " devient quelque chose comme un enum SYMBOL_PLUSPLUS. Plus tard, l'analyseur scène se transforme en un arbre de syntaxe abstraite, mais il ne peut pas changer les symboles. Vous pouvez affecter l'analyseur lexical en insérant des espaces (symboles de fin, à moins qu'ils sont entre guillemets).

Normal lexers sont avides (avec quelques exceptions), de sorte que votre code est interprété comme

a++ ++ +b

L'entrée de l'analyseur est un flux de symboles, de sorte que votre code serait quelque chose comme:

[ SYMBOL_NAME(name = "a"), 
  SYMBOL_PLUS_PLUS, 
  SYMBOL_PLUS_PLUS, 
  SYMBOL_PLUS, 
  SYMBOL_NAME(name = "b") 
]

Qui l'analyseur pense est syntaxiquement incorrect. (EDIT basée sur les commentaires: Sémantiquement incorrect parce que vous ne pouvez pas appliquer ++ pour une valeur de r, qui a++ résultats)

a+++b 

est

a++ +b

Qui est ok. Il en est de vos autres exemples.

98voto

Prasoon Saurav Points 47488

printf("%d",a+++++b); est interprété comme (a++)++ + b selon l'Maximale de Munch à la Règle!.

++ (postfix) n'est pas évalué à un lvalue mais il exige de son opérande à un lvalue.

! 6.4/4 dit la prochaine prétraitement jeton est la plus longue séquence de caractères qui pourraient constituer un prétraitement jeton"

30voto

Jerry Coffin Points 237758

L'analyseur lexical utilise ce qui est généralement appelé un "maximum de munch" algorithme pour créer des jetons. Cela signifie que c'est la lecture de caractères, il maintient la lecture des caractères jusqu'à ce qu'il rencontre quelque chose qui ne peut pas être partie de la même jeton que ce qu'il a déjà (par exemple, si elle a été la lecture des chiffres de telle sorte à ce qu'il a est un nombre, si elle rencontre une A, il sait que ne peuvent pas faire partie du nombre. donc, il s'arrête et laisse l' A dans le tampon d'entrée à utiliser comme le début de la prochaine jeton). Il renvoie alors que le jeton à l'analyseur.

Dans ce cas, cela signifie que +++++ obtient lexed comme a ++ ++ + b. Depuis le premier post-incrémentation donne une rvalue, la seconde ne peut pas être appliquée, et le compilateur indique une erreur.

Juste FWIW, en C++, vous pouvez surcharger operator++ de rendement une lvalue, ce qui permet que cela fonctionne. Par exemple:

struct bad_code { 
    bad_code &operator++(int) { 
        return *this;
    }
    int operator+(bad_code const &other) { 
        return 1;
    }
};

int main() { 
    bad_code a, b;

    int c = a+++++b;
    return 0;
}

La compile et s'exécute (bien qu'il ne fait rien) avec les compilateurs C++ que j'ai à portée de main (VC++, g++, Comeau).

12voto

Péter Török Points 72981

Votre compilateur essaie désespérément de les analyser a+++++b, et l'interprète comme (a++)++ +b. Maintenant, le résultat de la post-incrémentation (a++) n'est pas une lvalue, c'est à dire qu'il ne peut pas être post-incrémenté à nouveau.

S'il vous plaît ne pas écrire un tel code dans la production de programmes de qualité. Pensez à ce pauvre gars à venir après vous, qui a besoin d'interpréter votre code.

10voto

Erik Points 38942
(a++)++ +b

a++ renvoie la valeur précédente, une rvalue. Vous ne pouvez pas incrémenter ce.

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