Question Besoin d'aide pour comprendre cela pour le code de boucle en C


Considérez le code suivant dans C:

void main()
{
    int a=0;

    for(printf("\nA"); a; printf("\nB"));

    printf("\nC");
    printf("\nD");     
}

Quand je le compile en utilisant Turb C ++ version 3.0 et gcc-4.3.4, j'obtiens comme résultat dans les deux cas:

A
C
D

Cependant, si je compile le code suivant:

void main()
{
    for(printf("\nA"); 0; printf("\nB"));

    printf("\nC");
    printf("\nD");
}

La sortie de gcc-4.3.4 est la même que dans le cas précédent, mais turbo c ++ 3.0 produit la sortie suivante:

A
B
C
D

Tout d'abord, je n'ai aucune idée de ce qui se passe ici! De plus, comment se fait-il que la sortie du compilateur gcc soit la même pour les deux codes mais dans le cas du compilateur turboc ++ 3.0, la sortie est différente? Quelqu'un peut-il s'il vous plaît faire la lumière?

MODIFIER :

En fait, quelqu'un a posé cette question lors d'une interview pour une entreprise informatique et, lorsqu'il n'a pas répondu, l'interviewer a donné cette explication. Mais je trouve cela stupide. Comment pouvez-vous demander à quelqu'un d'utiliser un "bug" comme s'il s'agissait d'une "fonctionnalité" fournie par le langage? Pour qu'il soit appelé "facility" et "technique", que nous passions 0 comme littéral dans la deuxième expression ou une variable dont la valeur est 0, le résultat aurait dû être le même.

Est-ce que je me trompe en concluant que l'intervieweur était très stupide de poser une question comme celle-là et que cela montre son incompétence?


10
2018-06-18 16:08


origine


Réponses:


La sortie TCC du deuxième exemple est incorrecte.

De la norme C99:

La déclaration

pour (  clause 1  ;  expression-2  ;  expression-3  )  déclaration

se comporte comme suit: L'expression expression-2 est le contrôle   expression qui est évaluée avant chaque exécution du corps de la boucle.   L'expression expression-3 est évalué comme une expression vide après   chaque exécution du corps de la boucle. [...]

De toute évidence, il n'y a pas d'itérations ici, donc expression-3 ne devrait jamais être exécuté.

De même, dans la norme C90 (ou du moins dans un projet que j'ai trouvé), ça dit:

Sauf pour le comportement d'une instruction continue dans le corps de la boucle, le   déclaration

     for (  expression-1 ;  expression-2 ;  expression-3 )  statement

et la séquence des déclarations

      expression-1 ;
     while ( expression-2) {
               statement
              expression-3 ;
     }

sont équivalents.


12
2018-06-18 16:15



Turbo C ++ 3.0 est sorti dans les années 90 et a été très rapidement suivi par une version 3.1.

Je suppose que votre ancien compilateur contenait un certain nombre de bogues, qui ont été mis à jour rapidement. En outre, il pourrait ne pas ont eu de tels bugs, mais peuvent avoir émis un assemblage optimisé qui échoue sous les nouvelles architectures de revêtement de tuyaux.

En tout cas, c'est garanti que Turbo C ++ 3.0 est non supporté sur votre plateforme actuelle. Quand un compilateur n'est pas supporté car la plate-forme a été créée près de 20 ans plus tard, vous ne pouvez pas vraiment lui reprocher d'avoir émis un programme incorrect.


3
2018-06-18 16:19



La sortie gcc est correcte.

La sortie Turbo C ++ 3.0 dans le premier cas est correcte.

La sortie TurboC ++ 3.0 dans le second cas est incorrecte.

Dans le compilateur Turbo C ++ 3.0, il semble que vous ayez trouvé un casse, conduisant à une génération de code incorrecte.

Un for-stmt en C ou C ++ a la syntaxe générale

pour (initialisation; test; réinitialisation) stmt

Les initialisations sont effectuées une fois avant le début de la boucle. Le test est effectué au sommet de la boucle. Si le test est vrai, le stmt est exécuté, puis les réinitialisations et la boucle se répètent.

Dans votre cas, printf ("\ nA") est l'initialisation, un (ou 0) est le test, printf ("\ nB") est la réinitialisation et le stmt est vide.

Vous auriez dû voir le A (et vous l'avez fait). Le test aurait du échouer au premier passage, ce qui signifie que vous ne devriez jamais avoir vu le stmt (mais vous ne le savez pas), et vous ne devriez jamais avoir vu le B. C'est là que Turbo C ++ 3.0 a été vicié au deuxième test.


2
2018-06-18 16:20



Quelle est la syntaxe complète de la boucle "for" en C (et d'autres si elles sont compatibles)?

Cette question cite la partie applicable de la norme. La 3ème expression ne devrait pas être évaluée à moins que la boucle ne soit exécutée au moins une fois. Donc, je dirais que dans le second cas, l'ancien compilateur a tort d'imprimer «B».


1
2018-06-18 16:16



la sémantique de for est que la première expression est évaluée (initialiseur) alors la deuxième expression est évaluée (terminateur) puis si le terminateur évalué à non-nul le corps du for est exécuté, alors la troisième expression (avancement) est évaluée et revient à évaluer le terminateur.

Comme vous n'avez pas de corps, cette partie ne correspond à aucune expression évaluée. Sur cette base, la boucle doit être exécutée comme suit:

printf("\nA");
a; // yields 0 -> terminate loop

C'est en effet ce qui se passe.

Dans votre deuxième exemple, la même chose devrait se produire (comme pour gcc) 0 vaut 0.

Il est possible que turbo C ++ - voir la constante 0 - tenté d'effectuer une sorte d'optimisation du déroulement de la boucle (et échoué à le faire correctement)


1
2018-06-18 16:20