Sortie inattendue lors de l’exécution d’un décalage à gauche de 32 bits

Quand je fais un décalage à gauche d’un hex, j’obtiens -1 en sortie avec le code suivant:

unsigned int i,j=0; i= (0xffffffff << (32-j)); printf("%d",i); 

De même, lorsque j’ai changé la valeur de décalage en 32, la sortie est 0, mais le compilateur me signale les avertissements suivants (left shift count >= width of type)

 unsigned int i,j=32; i= (0xffffffff << (32)); printf("%d",i); 

Je m’attendais aux mêmes résultats dans les deux cas (c’est-à-dire 0), mais je ne comprends pas pourquoi le résultat affiché est incorrect dans le cas n ° 1 et, dans le cas n ° 2, le résultat est correct mais le compilateur vous avertit!

Le résultat est identique dans les machines x86 32 et 64 bits.

Quelqu’un peut-il expliquer les résultats ci-dessus?

C’est un comportement indéfini de laisser chier 32 ou plus sur un entier 32 bits. C’est ce que l’erreur est à propos.

C11 6.5.7 Opérateurs de décalage binary

Les promotions entières sont effectuées sur chacun des opérandes. Le type de résultat est celui de l’opérande gauche promu. Si la valeur de l’opérande de droite est négative ou est supérieure ou égale à la largeur de l’opérande de gauche promu, le comportement n’est pas défini.

Décaler une variable 32 bits de 32 génère un comportement indéfini.

Voici l’assemblage généré par le compilateur VS-2013:

  int n = 0; mov dword ptr [n],0 int a = 0xFFFFFFFF << 32; mov dword ptr [a],0 int b = 0xFFFFFFFF << (32-n); mov ecx,20h sub ecx,dword ptr [n] or eax,0FFFFFFFFh shl eax,cl mov dword ptr [b],eax 

Comme vous pouvez le constater, ce qui se passe de facto est:

  • Lorsque vous décalez d’une valeur constante de 32, le compilateur atsortingbue simplement le résultat à 0
  • Lorsque vous passez d’une variable (telle que 32-n avec n==0 ), le compilateur utilise shl

Le résultat réel de shl dépend de la mise en œuvre de cette opération dans l'architecture sous-jacente. Sur votre processeur, il prend probablement le deuxième opérande modulo 32, par conséquent le premier opérande est décalé de 0.

Encore une fois, la description ci-dessus n'est pas dictée par la norme, elle dépend donc vraiment du compilateur utilisé.