Je suis un peu confus parce que je voulais initialiser une variable de type unsigned long
dont la taille est de 8 octets sur mon système (sur tous les systèmes modernes, je suppose). Quand je veux assigner 1 << 63
à la variable, je reçois un avertissement du compilateur cependant et le nombre est en fait 0. Quand je fais 1 << 30
j’obtiens le résultat attendu de 2 ^ 30 = 1073741824
. Pourtant, quand je fais 1 << 31
, j’obtiens le résultat de 2 ^ 64
(je pense; en fait, cela ne devrait pas être possible) qui 18446744071562067968
.
Quelqu’un peut-il m’expliquer ce comportement?
1 << 63
sera calculé en arithmétique int
, et votre int
est probablement de 32 bits.
Remédier à cela en promouvant l'un des arguments: 1ULL << 63
fera.
ULL
signifie que l'expression sera d'au moins 64 bits.
L’expression 1 << 63
a le type int
. La plage d'un int
est comprise entre -2 31 … 2 31 - 1 sur la plupart des systèmes, 2 63 est trop grande pour cela. Essayez soit (unsigned long)1 << 63
ou 1UL << 63
pour décaler une valeur de type unsigned long
left de 63 places.
Je vous recommande d’utiliser 1ULL
car cela vous donnera un entier non signé 64 bits sur une architecture 32 et 64 bits. Sur une architecture 32 bits, la unsigned long
(et donc UL
) n’est que de 32 bits et ne résoudra pas le problème.
1ULL << 63
Le 1
ici s’appelle une constante entière . Selon les normes spécifiées dans la norme, C11
, chapitre §6.4.4.1
la syntaxe est la même.
constante entière:
suffixe entier décimal constant opt
suffixe entier- octal constant opt
hexadecimal-constant suffixe entier opt
et en ce qui concerne la sémantique,
Le type d’une constante entière est le premier de la liste correspondante dans laquelle sa valeur peut être représentée.
et la table indique, s’il n’y a pas de suffixe, et que la valeur est représentable dans la plage int
, elle doit être considérée comme int
. Donc, 1
ici, est considéré comme un int
, qui est généralement de 4 octets, ou 32 bits, également identique dans votre cas.
Pour spécifier explicitement le bit 1
unsigned long
(64), nous pouvons utiliser le suffixe, comme
1UL << 63
devrait résoudre votre problème.
S'il vous plaît noter: unsigned long
n'est pas garanti d'être de 64 bits. unsigned long long
est garanti pour avoir au moins 64 bits . Cependant, tant que vous utilisez la plate-forme où la unsigned long
est de 64 bits, tout devrait bien aller.