2010-03-07 25 views
4

En fonctionnement C, l'associativité est en tant que telle pour l'incrémentation, la décrémentation et l'affectation.L'associativité de l'opérateur dans l'incrément et le décrément de préfixes et de postfixes spécifiques C

2. postfix ++ and -- 
    3. prefix ++ and -- 
    16. Direct assignment = 

La liste complète se trouve ici Wikipedia Operators in C

Ma question est quand nous avons

int a, b; 

b = 1; 
a = b++; 

printf("%d", a); // a is equal to 1 

b = 1; 
a = ++b; 

printf("%d", a); //a is equal to 2 

Pourquoi un égal à 1 avec b ++ lorsque l'opérateur incrément postfix devrait se produire avant l'affectation directe ?

Et pourquoi l'opérateur d'incrémentation de préfixe est-il différent du suffixe quand ils sont tous les deux avant l'affectation? Je suis assez sûr que je ne comprends pas quelque chose de très important quand il s'agit de l'associativité des opérations.

Répondre

14

L'opérateur postfix a++ incrémente a puis retourner la valeur initiale, ce semblable à ceci:

{ temp=a; a=a+1; return temp; } 

et le préfixe ++a retourne la nouvelle valeur à savoir

{ a=a+1; return a; } 

Ce n'a rien à voir l'opérateur précédence.

(Et associativité gouverne si a-b-c égal à (a-b)-c ou a-(b-c).)

5

priorité des opérateurs et associativité ne vous dit pas ce qui se passe avant et ce qui se passe après. La précédence/l'associativité de l'opérateur n'a rien à voir avec cela. Dans le langage C, les relations temporelles comme "avant" ou "après" sont définies par des points de séquence et seulement par points de séquence (et c'est une histoire totalement distincte).

La priorité d'opérateur/associativité vous indique simplement quels opérandes appartiennent à quels opérateurs. Par exemple, l'expression a = b++ peut être formellement interprétée comme (a = b)++ et comme a = (b++). La priorité d'opérateur/associativité est ce cas vous indique simplement que cette dernière interprétation est correcte et que la première est incorrecte (c'est-à-dire ++ s'applique à b et non au résultat de a = b).

Cela ne signifie pas, une fois de plus, que b doit être incrémenté en premier. La précédence/l'associativité de l'opérateur, encore une fois, a à voir avec ce qui se passe "en premier" et ce qui se passe "en suivant". Il vous indique simplement que le résultat de l'expression b++ est affecté à a. Par définition, le résultat de b++ (incrément de suffixe) correspond à la valeur d'origine de b. Voilà pourquoi a va obtenir la valeur originale de b, qui est 1. Lorsque la variable b sera incrémentée est complètement hors de propos, tant que a est attribué, b « s valeur originale.Le compilateur est autorisé à évaluer cette expression dans n'importe quel ordre et incrémenter b à tout moment: tout va, tant que a obtient la valeur (et personne ne se soucie vraiment comment ça fonctionne "en quelque sorte" en interne).

Par exemple, le compilateur peut évaluer a = b++ comme la séquence suivante d'opérations élémentaires

(1) a := b 
(2) b := b + 1 

ou il peut l'évaluer comme suit

(1) b := b + 1 
(2) a = b - 1 

Notez que dans le premier cas b est en fait incrémentée à la fin, tandis que dans le second cas b est incrémenté en premier. Mais dans les deux cas a obtient la même valeur correcte - la valeur d'origine de b, qui est ce qu'il devrait obtenir.

Mais je dois réitérer que les deux exemples ci-dessus sont ici seulement à des fins d'illustration. En réalité, les expressions comme a = ++b et a = b++ n'ont pas de points de séquence à l'intérieur, ce qui signifie que de votre point de vue tout ce qui se passe dans ces expressions simultanément . Il n'y a pas de "avant", "après", "premier", "suivant" ou "dernier". De telles expressions sont "atomiques" dans un sens qu'elles ne peuvent pas être décomposées de manière significative en une séquence de plus petites étapes.

+1

'L'associativité de l'opérateur vous indique simplement quels opérandes appartiennent à quels opérateurs' ...... La précédence de l'opérateur indique que l'associativité de l'opérateur ..not. L'associativité des opérateurs entre en jeu lorsque des opérateurs ont la même priorité. Dans ce cas, «++» a une priorité plus élevée que '=' donc 'a = b ++' est interprété comme 'a = (b ++)' –

+2

@Prasoon Saurav: Chaque fois que l'associativité de l'opérateur "entre en jeu", elle vous dit toujours quels opérandes appartiennent à quels opérateurs. En fait, le langage C n'a pas de «priorité d'opérateur» et «d'associativité d'opérateur». Vous ne trouverez rien de tel dans la norme. Le langage C a une grammaire qui définit tout. "Associativité" et "préséance" ne sont rien d'autre qu'une tentative de présenter les règles de la grammaire sous une forme plus lisible. L'associativité et la précédence ont les mêmes racines et font la même chose. – AnT

+0

J'apprécie votre point de vue. 'Par exemple, l'expression a = b ++ peut être formellement interprétée comme (a = b) ++ et comme = (b ++)' et c'est à cause de la priorité de l'opérateur non pas à cause de l'associativité de l'opérateur. –

1

Comme AndreyT l'a déjà souligné, la précédence et l'associativité ne vous renseignent pas sur l'ordre d'évaluation. Ils ne vous disent que sur le regroupement. Par exemple, la priorité est ce qui indique à l'utilisation que a*b+c est regroupé en (a*b)+c au lieu de a*(b+c). Le compilateur est libre d'évaluer a, b et c dans l'ordre qu'il juge approprié avec l'une de ces expressions. L'associativité vous indique le regroupement lorsque vous avez des opérateurs de même priorité, le plus souvent les mêmes opérateurs. Par exemple, c'est ce qui vous indique que a-b-c est équivalent à (a-b)-c, et non a-(b-c) (autrement dit, la soustraction est laissée associative).

L'ordre d'évaluation est défini par des points de séquence. Il y a un point de séquence à la fin d'une expression complète (entre autres choses). Au point de séquence, toutes les évaluations précédentes doivent avoir eu lieu, et aucune des évaluations ultérieures ne peut avoir encore eu lieu.

En regardant vos exemples spécifiques, dans a=b++;, le résultat provient principalement de la définition de post-incrément elle-même. Un post-incrément donne la valeur précédente de la variable, et parfois avant le point de séquence suivant, la valeur de cette variable sera incrémentée. Un pré-incrément donne la valeur de la variable avec l'incrément appliqué. Dans aucun des deux cas, cela ne signifie que la variable doit être incrémentée dans un ordre particulier par rapport à l'affectation. Par exemple, dans votre exemple pré-incrément, le compilateur est entièrement libre de faire quelque chose d'équivalent à:

temp = b+1; 
a = temp; 
b = b + 1; 

De même, dans la version post-incrément, peut être incrémenté la variable avant ou après la cession:

a = b; 
b = b + 1; 

ou:

temp = b; 
b = b + 1; 
a = temp; 

Quoi qu'il en soit, cependant, la valeur attribuée à a doit être la valeur de b avant qu'il ne soit incremente ré.