56 votes

La boucle commençant à -1 n'imprime rien

Ce programme est censé imprimer les éléments de array , mais lorsqu’il est exécuté, aucun résultat n’est affiché.

 #include <stdio.h>

#define TOTAL_ELEMENTS  (sizeof(array) / sizeof(array[0]))

int array[] = { 23, 34, 12, 17, 204, 99, 16 };

int main() {
    int d;
    for (d = -1; d <= (TOTAL_ELEMENTS - 2); d++) 
        printf("%d\n", array[d + 1]);
    return 0;
}
 

Pourquoi ce programme ne montre aucune sortie?

157voto

coldspeed Points 111053

sizeof renvoie un entier non signé, donc TOTAL_ELEMENTS est également signée.

d est signé. D'abord, d est -1. Cependant, lorsque l'on fait la comparaison, d est implicitement transtypage non signé, donc il n'est plus -1 lorsque comparé TOTAL_ELEMENTS, il est en fait UINT_MAX (ce qui est 4294967295 sur ma machine, mais peuvent différer pour les autres).

Aussi,

Si vous voulez résoudre ce problème, catalogué TOTAL_ELEMENTS de int:

for(d = -1; d <= (int)(TOTAL_ELEMENTS - 2); d++) 

Ce sera d'impression:

23
34
12
17
204
99
16

Comme vous pouvez vous attendre. Vous pouvez également regarder opération de Comparaison sur non signés et les entiers signés pour plus d'information sur le thème de " signé non signé comparaisons.

Il est intéressant de noter que le tournage sur les avertissements du compilateur serait avez vous a aidé à comprendre ce qui se passe (comme observé par hyde dans son commentaire):

$ gcc -Wall -Wextra test.c
test.c:7:17: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
      for(d = 0; d < TOTAL_ELEMENTS; d++) 
              ~ ^ ~~~~~~~~~~~~~~
1 warning generated.

Sinon, pourquoi ne pas commencer d à 0 et exécuter d' TOTAL_ELEMENTS - 1 à la place? Vous pouvez même laisser tomber le transtypage, qui est nécessaire seulement pour le cas de coin de d = -1.

for(d = 0; d < TOTAL_ELEMENTS; d++) 
    printf("%d\n", array[d]);

Comme une note de bas de page, voici les Standard C99 extraits:

  1. 6.3.1.8p2 définit la conversion d'une signature de type non signé.

    Si l'opérande qui a unsigned integer a rang supérieur ou égal au rang de la catégorie de l'autre opérande, puis l'opérande de type entier signé est converti dans le type de la opérande de type entier non signé.

  2. 6.3.1.3p2 définit la façon dont la conversion est faite: Par l'ajout d' UINT_MAX + 1 à la signature de la représentation.

    Si le nouveau type est non signé, la valeur est convertie à plusieurs reprises par l'ajout ou la soustraction d'une plus de la valeur maximale qui peut être représenté dans le nouveau type jusqu'à ce que la valeur est dans l' la gamme du nouveau type.

    Donc, -1 => -1 + (UINT_MAX + 1) = UINT_MAX, pour ce scénario.

40voto

CIsForCookies Points 6642

Mon gcc émet cet avertissement:

 warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
      for(d = 0; d < TOTAL_ELEMENTS; d++) 
 

ce qui signifie que (TOTAL_ELEMENTS-2) est unsigned int alors que d est signed int . Cela rend l'expression toujours false pour la valeur initiale de d , puisque (unsigned int)(-1) > (TOTAL_ELEMENTS-2) .

6voto

Patt Points 59

Les opérations binaires entre différents types d'intégraux sont effectuées au sein d'un type "commun" défini par les conversions arithmétiques habituelles. So int d est de type singularisé initialisé avec la valeur -1. Lorsqu’il est converti en unsigned int, il retournera un maximum d’un unsigned int, qui est beaucoup plus grand que la valeur renvoyée par TOTAL_ELEMENTS.

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