Si les parenthèses ont une priorité plus élevée, alors pourquoi l'opérateur increment est-il résolu en premier?

j'ai un code à une ligne,

int a = 10;
a = ++a * ( ++a + 5);

ma production attendue était 12 * (11 + 5) = 192 , mais j'ai obtenu 187 . Autant que je sache, l'opérateur d'incrémentation à l'intérieur () doit être résolu en premier, puis les raisons de l'extérieur est résolu en premier?

41
demandé sur frunkad 2015-01-29 19:14:23

5 réponses

Les Expressions

sont évaluées de gauche à droite. Les parenthèses (et la préséance) expriment simplement le groupement, elles n'expriment pas l'ordre de l'évaluation.

Donc

 11 * (12 + 5)
++a   ++a

égale

187
97
répondu Sotirios Delimanolis 2017-11-14 15:12:21

citant le Blog D'Eric Lippert :

l'évaluation d'une expression arithmétique est contrôlée par trois ensembles de règles: règles de préséance, règles d'associativité et règles d'ordre.

priorité les règles décrivent comment une expression sous-divisée doit être mise entre parenthèses lorsque l'expression mélange différents types d'opérateurs.

Associativité règles de décrire comment un underparenthesized expression doivent être mis entre parenthèses lorsque l'expression a un tas de la nature même de l'opérateur.

ordre d'évaluation les règles décrivent l'ordre dans lequel chaque opérande d'une expression est évaluée.

priorité supérieure entraîne le groupement des opérandes avec un opérateur et ne signifie pas l'évaluation des opérandes. Il est l'ordre d'évaluation qui détermine la séquence d'évaluation des sous-expressions d'une expression.


mise à Jour:

comme je peux voir beaucoup de programmeurs pensent que la déclaration

a = ++a * ( ++a + 5);  

va invoquer un comportement non défini. Oui, il va invoquer l'AC s'il n'y a pas de garantie d'ordre d'évaluation des opérandes d'un opérateur.

Mais ce n'est pas vrai dans le contexte de la programmation java langue. Il a un comportement bien défini en java (ainsi qu'en C#). La spécification Java Language stipule que:

15.7. Ordonnance D'Évaluation

le langage de programmation Java garantit que les opérandes des opérateurs semblent être évaluées dans un ordre d'évaluation spécifique, à savoir, de gauche à droite .

exemple 15.7.1-1. L'Opérande De Gauche Est Évaluée En Premier

dans le programme suivant, l'opérateur * a un opérande de gauche qui contient une assignation à une variable et un opérande de droite qui contient une référence à la même variable. La valeur produite par la référence reflétera le fait que l'affectation a eu lieu en premier.

class Test1 {
    public static void main(String[] args) {
        int i = 2;
        int j = (i=3) * i;
        System.out.println(j);
    }
}

ce programme produit le résultat:

9

il n'est pas permis pour l'évaluation de l'opérateur * de produire 6 au lieu de 9 .

mais, encore spécification java indique clairement que de ne pas écrire de tels codes:

il est recommandé que le code ne s'appuie pas fondamentalement sur cette spécification . Le Code est généralement plus clair lorsque chaque expression contient au plus un effet secondaire, comme son extrémité le fonctionnement, et quand le code ne dépend pas exactement de quelle exception découle comme une conséquence de l'évaluation gauche-à-droite des expressions.

29
répondu haccks 2015-01-30 14:16:41

de cet extrait

int a = 10;
a = ++a * ( ++a + 5);

parfois, la solution la plus simple est d'utiliser javap pour comprendre l'ordre d'évaluation:

 0: bipush 10 // push 10 onto the stack (stack={10})
 2: istore_1  // store 10 into variable 1 (a = 10, stack={})
 3: iinc 1, 1 // increment local variable 1 by 1 (a = 11, stack={})
 6: iload_1   // push integer in local variable 1 onto the stack (a = 11, stack = {11})
 7: iinc 1, 1 // increment local variable 1 by 1 (a = 12, stack={11})
 10: iload_1  // push integer in local variable 1 onto the stack (a = 12, stack = {12, 11})
 11: iconst_5 // load the int value 5 onto the stack (a = 12, stack = {5, 12, 11})
 12: iadd     // add 5 and 12 (a = 12, stack = {17, 11})
 13: imul     // multiply 17 and 11 (a = 12, stack = {})
  1. a est incrémenté de 1. (ligne 3) // a = 11
  2. a est incrémenté de 1. (ligne 7) // a = 12
  3. ajouter 5 à a (ligne 12) / / a = 17
  4. multiplier 11 par 17 (ligne 13) / / a = 187

(10 + 1 + 1 + 5) * 11 = 187

10
répondu Pier-Alexandre Bouchard 2015-02-01 04:33:25

l'effet des parenthèses est de contrôler quelles valeurs calculées sont utilisées comme opérandes pour des opérations ultérieures. Ils contrôlent l'ordre dans lequel les opérations sont effectuées uniquement dans la mesure où une opération ne peut être évalué qu'après ses opérandes ont été. Considérez les expressions:

(a()+b()) * (c()+d())
a() + (b()*c()) + d()

la parenthèse ne doit pas (et en Java ne peut pas) affecter l'ordre dans lequel a(), b(), c(), et d() sont appelés. Ils peuvent affecter si la multiplication est exécuté avant ou après que d () soit appelé, mais seulement dans de très rares circonstances (par exemple d () appelant une Interface Java Native qui modifie le mode d'arrondi numérique utilisé dans la multiplication D'une manière que Java ne connaît pas) le code aurait n'importe quel moyen de savoir ou de se soucier si la multiplication a été effectuée avant ou après d ().

sinon, ce qui est important, c'est que dans le premier cas, une opération d'addition agira sur a() et b (), et l'autre sur c() et d(); Le la multiplication agit sur a()+b() et c()+d(). Dans l'autre cas, la première multiplication agira sur b() et c(), la première addition sur a() et le produit susmentionné, et la seconde addition sur la première somme et d().

2
répondu supercat 2015-01-29 19:16:34
  int a = 10;
  a = ++a * ( ++a + 5);

les types d'expressions ci-dessus sont toujours évalués de gauche à droite que ce soit en C ou en JAVA

dans ce cas, il résout comme ceci 11*(12+5) ce qui donne 11*17 = 187 // W. R. t java

mais si cela nous résolvons la même expression W. R. t C-langue

puis la réponse est changée comme la façon d'évaluer change

en c premier pré-incrément / pré-décrément se produit, donc si" N " Non de l'époque pré inc/dec y at-il dans l'expression alors inc / dec se produira d'abord "N" nombre de fois

alors la même valeur sera substituée dans chaque occurrence de la variable dans l'expression et la valeur de l'expression est calculée et après que l'incrément/décrément post se produit

I. e A est incrémenté à 11 puis à nouveau 12 car il y a deux incréments pour a dans l'expression et puis l'expression est évaluée comme

12*(12+5)=12*17=204 //w.R. t C-langue

-1
répondu Debpratim Ghosh 2015-02-04 01:15:16