URL: https://linuxfr.org/users/blackknight/journaux/un-decalage-de-64-bits-ca-vous-inspire-comment Title: Un décalage de 64 bits, ça vous inspire comment ? Authors: Blackknight Date: 2017年05月14日T17:18:57+02:00 License: CC By-SA Tags: programmation, freepascal, ada, ocaml et python Score: 46 Salut à tous, après l'[excellent journal](https://linuxfr.org/users/anaseto/journaux/un-print-1-3a-ca-nous-inspire-comment) d'Anaseto sur le fameux "1+3a", un pote à moi, prof de maths à L'INSA de Rouen, m'a demandé de faire ce petit journal après une "découverte" faite par ses étudiants. Ceux-ci écrivant des tests unitaires en [[Free Pascal]] sont tombés sur un comportement non documenté qui nous a amené à nous poser la question du "comment ksa fait sur les autres langages" :) # Le problème # Le problème vient de l'opérateur de décalage de bits à droite. Si je prend un entier initialisé à 1, le décalage d'un bit vers la droite retourne 0. Si l'on décale de 2 bits, on s'attend à avoir 0... Et c'est toujours le cas. Par contre, le code suivant ne retourne pas 0 ```pascal program beBitwise; var a, b: integer; begin a := 1; b := a>> 64; (* la, on s'attend normalement à obtenir un 0 *) writeln('Valeur de b ', b ); end. ``` Le code retourne 1 à savoir _a_. Si l'on remplace 64 par 63 ou 65, on obtient bien 0. Bien sûr, sur une machine 32 bits, on obtient le même comportement avec un décalage de 32 bits. Si le comportement peut s'expliquer, le fait que le compilateur ne prévienne pas du risque et qu'aucune documentation ne le spécifie est un poil gênant. Résultat, les étudiants sont en train de remplir un rapport de bug pour _Free Pascal_, ne serait-ce que pour que le comportement soit documenté quelque part. Et chez les autres ? ## En C/C++ ## ```c++ #include using namespace std; int main(int argc, char** argv) { unsigned long long a = 1; unsigned long long b = a << 64; cout << "b vaut " << b << endl; } ``` Au moins, le compilateur GCC nous prévient du problème en affichant le warning si on travaille en statique shift.cpp: In function ‘int main(int, char**)’: shift.cpp:8:31: warning: left shift count>= width of type [-Wshift-count-overflow] unsigned long long b = a << 64; Dans le cas où c'est l'utilisateur qui rentrerait le décalage à l'exécution, il n'y aurait aucun message... Logique ! ## En Java ## ```java public class Shift { public static void main(String[] args) { int a = 1; System.out.println("Resultat : " + (a>> 64)); } } ``` Même punition et surtout pas de warning. ## En Ada ## Vous n'y couperez pas, je vais forcément donner un exemple en Ada ```Ada with Interfaces; use Interfaces; with Ada.Text_Io; use Ada.Text_Io; Procedure Shift is begin Put_Line("Resultat " & Unsigned_64'Image(Shift_Right(Unsigned_64(1), 64))); end Shift; ``` Là, pas de message d'erreur ni de warning mais au final pas d'erreur non plus, le résultat est bien 0. ## En OCAML ## Il s'agit juste d'une ligne de commande dans l'interpréteur: ```ocaml # open Int64;; # shift_right one 64;; - : int64 = 1L # ``` J'avoue que je ne m'attendais pas à ce résultat mais OCAML retourne lui aussi 1 en lieu et place de 0. ## En Python ## ```python>>> 1>> 64 0 ``` Ce qui est normal pour un langage typé canard ;) # Que disent les docs ? # Le reproche que l'on peut faire à Free Pascal, c'est justement de ne rien dire quant à ce fonctionnement. Par contre, si l'on prend [[OCAML]], [la documentation du module _Int64_](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Int64.html) précise que le comportement est non spécifié. val shift_right : int64 -> int -> int64 Int64.shift_right x y shifts x to the right by y bits. This is an arithmetic shift: the sign bit of x is replicated and inserted in the vacated bits. The result is unspecified if y < 0 or y>= 64. Si on prend les deux langages normalisés, à savoir C++ et Ada, la documentation est claire. Pour C++, dans le [_draft_ de la prochaine norme](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf), page 126, le comportement est _implementation defined_. Pour Ada, il n'y a aucune restriction et [la norme](http://www.ada-auth.org/standards/rm12_w_tc1/html/RM-B-2.html) ne fournit donc que les exigences d'implémentation. Voilà pour les langages que j'ai eu envie d'explorer. Et vous, votre langage préféré, il fait quoi ?

AltStyle によって変換されたページ (->オリジナル) /