80 votes

Programme se comportant étrangement sur les IDE en ligne

J'ai trouver ci-dessous un programme C++ (source):

#include <iostream>
int main()
{
    for (int i = 0; i < 300; i++)
        std::cout << i << " " << i * 12345678 << std::endl;
}

Il ressemble à un programme simple et donne de bons résultats sur ma machine locale, c'est à dire quelque chose comme:

0 0
1 12345678
2 24691356
...
297 -628300930
298 -615955252
299 -603609574

Mais, sur en ligne IDEs comme codechef, il donne le résultat suivant:

0 0
1 12345678
2 24691356
...
4167 -95167326
4168 -82821648
4169 -7047597

Pourquoi ne pas l' for boucle de mettre fin à 300? Aussi ce programme se termine toujours sur 4169. Pourquoi 4169 et pas une autre valeur?

105voto

user2079303 Points 4916

Je vais supposer que le site de l'compilateurs GCC ou compatible compilateur. Bien sûr, tout autre compilateur est également autorisé à faire la même optimisation, mais GCC documentation explique bien ce qu'il fait:

-faggressive-loop-optimizations

Cette option indique la boucle optimiseur d'utiliser les contraintes de la langue pour dériver des valeurs limites pour le nombre d'itérations d'une boucle. Cela suppose que la boucle de code ne pas se prévaloir d'un comportement indéfini, par exemple, en provoquant signé des débordements d'entiers ou hors limites, accès à des tableaux. Les limites pour le nombre d'itérations d'une boucle sont utilisés pour guider le déroulement de la boucle et de l'épluchage et de sortie de boucle de test optimisations. Cette option est activée par défaut.

Cette option permet simplement de faire des hypothèses sur la base de cas où l'AC est prouvé. Pour profiter de ces hypothèses, d'autres optimisations peuvent avoir besoin d'être activé, comme le pliage de constante.


Signé débordement d'entier a un comportement indéterminé. L'optimiseur a été en mesure de prouver que toute valeur de i de plus de 173 serait la cause de l'AC, et parce qu'il peut supposer qu'il n'y est pas de l'AC, il peut aussi supposer que i n'est jamais plus grande que 173. Il peut alors prouver que i < 300 est toujours vrai, et donc la condition de la boucle peut être optimisé à l'écart.

Pourquoi 4169 et pas une autre valeur?

Ces sites probablement limiter le nombre de lignes de sortie (ou de caractères ou d'octets) qu'ils montrent et partagent la même limite.

37voto

HolyBlackCat Points 2137

"Undefined comportement est indéfini." (c)

Un compilateur utilisé sur codechef semble utiliser la logique suivante:

  1. Comportement indéfini ne peut pas se produire.
  2. i * 12345678 , des débordements et des résultats dans l'AC s' i > 173 (en supposant que le 32 bits, ints).
  3. Ainsi, i ne peut jamais excéder 173.
  4. Ainsi, i < 300 est superflu et peut être remplacé par true.

La boucle elle-même semble être infinie. Apparemment, codechef arrête le programme après une période de temps spécifique ou tronque la sortie.

10voto

Ron Points 10773

Vous êtes en invoquant un comportement indéfini probablement sur 174e itération à l'intérieur de votre for boucle comme le max int de la valeur sans doute est - 2147483647 encore 174 * 123456789 expression 2148147972 ce qui est un comportement indéfini comme il n'y a pas signé de dépassement d'entier. Si vous observez des effets de l'AC, en particulier avec le compilateur GCC avec les options d'optimisation défini dans votre cas. Il est probable que le compilateur vous aura prévenu, par la délivrance de l'avertissement suivant:

warning: iteration 174 invokes undefined behavior [-Waggressive-loop-optimizations]

Supprimer le (-O2) options d'optimisation afin d'observer des résultats différents.

7voto

yassin Points 520

Le compilateur peut supposer que le comportement non défini ne se produira pas et, comme le débordement signé est UB, il ne peut supposer que jamais i * 12345678 > INT_MAX , donc aussi i <= INT_MAX / 12345678 < 300 et supprime donc le contrôle i < 300 .

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