web-dev-qa-db-fra.com

Quelle est la valeur maximale d'une variable Shell bash numérique?

Je suis curieux de savoir ce qui se passe quand une variable numérique dans bash est incrémentée sans l'arrêter volontairement. Quelle taille peut atteindre le nombre? Est-ce qu'il débordera et deviendra négatif et continuera simplement à augmenter pour toujours? Est-ce que ça va casser et glisser jusqu'à un arrêt à un moment donné?

J'utilise un processeur AMD x86_64, mais je serais heureux d'entendre les réponses 32 bits également, précisez simplement de quoi vous parlez. Je cours Fedora21 64bit.

J'ai cherché Google très loin, mais je n'ai pas trouvé cette friandise spécifique pour une raison quelconque. Il semble que ce soit une information de base dans tous les manuels, etc.

15
Max Power

Cela peut venir de votre version de bash, de votre système d'exploitation et de votre architecture de processeur. Pourquoi tu ne l'essaies pas toi-même? Définissez une variable sur (2 ^ 31) -1, puis incrémentez-la, définissez-la sur 2 ^ 32, puis incrémentez-la, définissez-la sur 2 ^ 64, puis incrémentez-la, etc.

Ici, je viens de l'essayer moi-même sur mon Core i7 fonctionnant sous OS X "El Capitan" v10.11.3, et il semble que bash utilise des entiers 64 bits signés.

 $ uname -a 
 Darwin Spiff.local 15.3.0 Noyau Darwin Version 15.3.0: Jeu 10 déc 18:40:58 PST 2015; racine: xnu-3248.30.4 ~ 1/RELEASE_X86_64 x86_64 
 $ bash --version 
 bash --version 
 GNU bash, version 3.2.57 (1) - release (x86_64 -Apple-darwin15) 
 Droits d'auteur (C) 2007 Fondation du logiciel libre, Inc. 
 $ 
 $ ((X = 2 ** 16)); echo $ X 
 65536 <- d'accord, au moins UInt16 
 $ ((X = 2 ** 32)); echo $ X 
 4294967296 <- d'accord, au moins UInt32 
 $ ((X = 2 ** 64)); echo $ X 
 0 <- oops, pas UInt64 
 $ ((X = (2 ** 63) -1)); echo $ X 
 9223372036854775807 <- d'accord, au moins SInt64 
 $ ((X ++)); echo $ X 
 - 9223372036854775808 <- négatif débordé et enveloppé. Doit être SInt64 
19
Spiff

J'ai mis en place une boucle. while return status is 0 increment a variable with addition and print the variable to stdout Je l'ai démarré un peu moins de 2 ^ 31, je l'ai laissé passer sans problème, 2 ^ 31 et 2 ^ 32, je l'ai arrêté, puis j'ai réglé la valeur initiale sur un peu moins de 2 ^ 63. Le résultat est qu’il est passé sans interruption de 9.22e18 à -9.22e18 et continue d’augmenter de manière positive. (vers zéro)

Juste pour vérifier que mon while [ $? -eq 0 ] utilisait réellement le statut de sortie des commandes dans la boucle while, sans utiliser le statut de sortie du script précédent ou une anomalie, je l'ai également exécuté avec une commande supplémentaire à l'intérieur de la boucle conçue pour créer un non nul état de sortie à des incréments particuliers.

Donc, il est signé, il va basculer plutôt que de s'arrêter à la valeur maximale, et cela sans aucun message d'erreur. Il est donc possible de se retrouver dans une boucle véritablement infinie. Il ne limite pas le matériel 64 bits et le système d’exploitation Linux 64 bits à une ancienne norme 16 ou 32 bits.

3
Max Power

bash utilise un entier de 64 bits. Donc si vous augmentez après que la variable ait atteint son nombre maximum, la variable débordera. Vous trouverez ci-dessous mon test avec un entier non signé et un entier signé.

MAX_UINT = 18446744073709551615
MAX_INT = 9223372036854775807

$ printf "%llu\n" $((2**64))
0
$ printf "%llu\n" $((2**64-1))
18446744073709551615

$ printf "%lld\n" $((2**63-1))
9223372036854775807
$ printf "%lld\n" $((2**63))
-9223372036854775808
$ printf "%lld\n" $((2**64-1))
-1
1
PT Huynh