2010-08-02 20 views
2

quelqu'un me s'il vous plaît expliquer pourquoic tandis que l'entrée en boucle

int i=0,j=10; 
    while(j>0,i++){ 
    printf("%d%d",i,j); 
    j--; 
} 

ne fonctionnera pas et

int i=0,j=10; 
while(i++,j>0){ 
    printf("%d%d",i,j); 
    j--; 
} 

œuvres.

s'il vous plaît me dire aussi pourquoi

int i=0,j=10; 
while(j>0,++i){ 
    printf("%d%d",i,j); 
    j--; 
} 

donne une boucle infinie?

Merci et salutations

Harsha

+0

Ceci est totalement illisible .... s'il vous plaît utiliser les balises Markup à votre disposition ... –

+0

Comment peut-on (j> 0, ++ i) {} même compiler? – DixonD

+0

"while (j> 0, i ++)" ne compile pas !! – Vishal

Répondre

16

Dans votre état while vous utilisez opérateur virgule, qui évalue ses paramètres et retourne le second. Ainsi, dans vos exemples:

while(j>0,i++) - returns i before it gets incremented; 
       that is 0, so loop won't execute at all 

while(i++,j>0) - returns (j > 0) - runs as expected 

while(j>0,++i) - returns i - will run until i overflows max int value 
+1

Le premier sort immédiatement - c'est différent de # 3. Sinon correct. –

+0

Oui, vous avez corrigé cela – Vladimir

+2

Notez que dans le dernier exemple, au point où '++ i' déborde, la boucle ne sort pas * nécessairement * - le comportement devient indéfini. – caf

4

Lire sur le C comma operator. Fondamentalement, il se réduit au fait que l'opérateur virgule renvoie le résultat de tout ce qui se trouve sur le côté droit de la virgule - donc dans votre premier exemple, i ++ renvoie 0, et la boucle se termine. Dans le troisième cas, ++ i n'est jamais 0 (du moins pas longtemps) donc vous obtenez la boucle infinie. Le cas du milieu est correct, puisque le résultat de j>0 est renvoyé par l'opérateur virgule, et votre boucle fonctionne comme prévu.

+0

Je vois comment cela fonctionne, mais cet usage serait-il considéré comme une "bonne pratique" dans c? Cela semble un peu obscur. –

+0

Certainement pas. Qui, dans le bon esprit, utilise un opérateur de virgule dans la condition while? – Yuji

+0

La page que vous avez liée suggère que l'utilisation la plus courante est dans une boucle 'for', bien que les exemples donnés par l'auteur soient encore plus obscurs que la boucle' while' montrée ici. Il est difficile de dire quelle instruction est réellement retournée dans chaque partie de la boucle 'for'. –

1

Vous utilisez l'opérateur virgule. Le résultat de l'opérateur virgule est la deuxième sous-expression. Donc j>0,i++ évalue à i++. i++ est initialement 0, donc la boucle ne s'exécute jamais.

De même, j>0,++i évalue à , qui sera différent de zéro jusqu'à ce que vous débordiez, donc il semble boucler pour toujours (bien que vraiment juste pendant longtemps).

i++,j>0 fonctionne parce que la dernière sous-expression est j>0, qui est la condition réelle que vous souhaitez. Notez que même si l'opérateur virgule jette le résultat de la première expression (i++, dans ce cas), il évalue toujours cette sous-expression, et donc vous obtenez toujours l'effet secondaire (en incrémentant i).

0

Dans ces cas, vous avez des expressions qui incluent un opérateur de virgule. L'opérateur virgule évalue son opérande de gauche, puis son opérande de droite. Le résultat est celui de l'opérande droit.

Pour le moment, nous allons examiner seulement votre dernière question:

int i=0,j=10; 
while(j>0,++i){ 
    printf("%d%d",i,j); 
    j--; 
} 

Cela ne devrait pas vraiment être une boucle infinie, mais il peut courir un peu plus longtemps que prévu. Puisque le résultat de l'opérateur virgule est le résultat de l'opérande right, il attend ++i pour devenir 0. Comme il commence à 0, il va cycler à toutes les valeurs possibles d'un int avant qu'il se termine. Avec un int 16 bits, cela prendrait probablement quelques minutes. Avec un 32 bits int, il va prendre assez un peu plus longtemps.Avec un int 64 bits, serait être une boucle infinie pour n'importe quel but pratique - je suis sûr que je vais mourir longtemps avant qu'il pourrait espérer finir en tout cas ...

+0

Il fonctionnera au moins jusqu'à ce que «i» soit égal à «INT_MAX» - à ce moment, «++ i» déborde, ce qui entraîne un comportement indéfini. Cela signifie que * n'importe quoi * est possible, y compris une boucle infinie («++ i» pourrait bien laisser «i» inchangé!). – caf

+0

@caf: En théorie, tout à fait vrai. En fait, il est peu probable que vous voyiez quoi que ce soit de ce genre - bien qu'il y ait du matériel pour fournir des entiers saturés, je n'ai jamais vu quelqu'un l'utiliser pour un int normal. Étant donné le degré de similitude requis entre les variantes signées et non signées, et l'exigence que 'unsigned' wrap modulo 2^N-1, je ne suis pas sûr qu'il y a même du matériel qui * pourrait * le faire, même si c'est théoriquement possible. –

+0

Eh bien, la fonctionnalité de saturation serait un attribut de l'opération "ADD" - vous pourriez imaginer une architecture qui fournissait à la fois les instructions "Add-With-Saturate" et "Add-With-Wrap", avec un compilateur C utilisant le premier pour ajout signé et le dernier pour non signé. Beaucoup plus probable est cependant un piège sur débordement - si le piège est géré en sautant l'instruction de piégeage, alors il aurait aussi l'effet de saturation (bien qu'un abandon de programme soit beaucoup plus probable). – caf