Le décalage à droite d'un nombre de bits égal ou supérieur à sa taille est un comportement indéfini.
C11 6.5.7 opérateurs de décalage au niveau du bit
Syntaxe
shift-expression: additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
Contraintes
Chacun des opérandes ont type entier.
Sémantique
Les promotions entières sont effectuées sur chacun des opérandes. Le type du résultat est celui de l'opérande gauche promu. Si la valeur de l'opérande de droite est négative ou supérieure ou égale à la largeur de l'opérande gauche promu, le comportement n'est pas défini.
Le résultat de E1 << E2
est E1
décalé vers la gauche E2
positions de bit; les bits vides sont remplis de zéros. Si E1
a un type non signé, la valeur du résultat est E1
× 2 E2, modulo réduit d'un de plus que la valeur maximale représentable dans le type de résultat.Si E1
a un type signé et une valeur non négative, et E1
× 2 E2 est représentable dans le type de résultat, alors c'est la valeur résultante; sinon, le comportement est indéfini.
Le résultat de E1 >> E2
est E1
décalé à droite E2
positions de bit. Si E1
a un type non signé ou si E1 a un type signé et une valeur non négative, la valeur du résultat est la partie intégrale du quotient de E1
/2 E2. Si E1
a un type signé et une valeur négative, la valeur résultante est définie par l'implémentation.
La taille de int
sur votre plate-forme semble être à la plupart des 32 bits, de sorte que les initialisations pour bit32R
et bit32L
ont un comportement non défini.
Les expressions 64 bits doivent être écrits:
uint64_t bit32R = (uint64_t)code >> 32;
et
uint64_t bit32L = (uint64_t)code << 32;
De plus, les formats utilisés dans printf
ne sont pas correctes pour les arguments transmis (à moins int
a 64 bits, ce qui produirait une sortie différente).
Votre compilateur ne semble pas entièrement compatible C99, vous devez ajouter une instruction finale return 0;
à la fin du corps de la fonction main()
.
Voici une version corrigée:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
int main(void) {
uint32_t code = 0xCDBAFFEE;
uint64_t bit32R = (uint64_t)code >> 32;
uint16_t bit16R = code >> 16;
uint8_t bit8R = code >> 8;
uint8_t bit0R = code >> 0;
uint64_t bit32L = (uint64_t)code << 32;
uint16_t bit16L = code << 16;
uint8_t bit8L = code << 8;
uint8_t bit0L = code << 0;
printf("Right shift:\n"
"bit32R %.16"PRIx64"\n"
"bit16R %"PRIx16"\n"
"bit8R %"PRIx8"\n"
"bit0R %"PRIx8"\n\n",
bit32R, bit16R, bit8R, bit0R);
printf("Left shift:\n"
"bit32L %.16"PRIx64"\n"
"bit16L %"PRIx16"\n"
"bit8L %"PRIx8"\n"
"bit0L %"PRIx8"\n\n",
bit32L, bit16L, bit8L, bit0L);
return 0;
}
La sortie est:
Right shift:
bit32R 0000000000000000
bit16R cdba
bit8R ff
bit0R ee
Left shift:
bit32L cdbaffee00000000
bit16L 0
bit8L 0
bit0L ee
cela pourrait ne pas être ce que vous attendez, parce que les types des variables sont quelque peu contradictoires.
Votre code appelle un comportement indéfini. Une valeur de décalage de '32' est trop grande pour un' int' de 32 bits (même chose pour 16 bits si votre plate-forme a 16 bits 'int'). Et utilisez les macros 'PRInX' de' inttypes.h' pour imprimer des types à largeur fixe. Vous avez une mauvaise idée du fonctionnement des opérations entières. – Olaf
J'ai changé le fichier include en stdint! Ce qui n'a rien changé, mais j'ai oublié stdint, et inclus inttypes. Mais je pense qu'ils sont les mêmes, au moins pour mon code. –
Peut-être avant de faire des suppositions, c'est une bonne idée de lire ce que les en-têtes fournissent, comment ils sont liés et ce que signifie PRInX? – Olaf