2009-01-20 5 views
12

Je ne comprends pas cet opérateur de décalage (C# de référence):Comprendre l'opérateur de décalage

class MainClass1 
{ 
static void Main() 
    { 
     int i = 1; 
     long lg = 1; 
     Console.WriteLine("0x{0:x}", i << 1); 
     Console.WriteLine("0x{0:x}", i << 33); 
     Console.WriteLine("0x{0:x}", lg << 33); 
    } 
} 

/* 
Output: 
0x2 
0x2 
0x200000000 
*/ 

class MainClass2 
{ 
    static void Main() 
    { 
     int a = 1000; 
     a <<= 4; 
     Console.WriteLine(a); 
    } 
} 

/* 
Output: 
16000 
*/ 

Répondre

34

<< est l'opérateur de décalage vers la gauche; cela prend la représentation binaire d'une valeur, et déplace tous les bits "n" endroits vers la gauche (sauf pour "mod", voir "1"), remplissant avec des zéros.

>> est l'opérateur de décalage vers la droite; cela fait presque le contraire (en se déplaçant vers la droite), à ​​l'exception des valeurs signées (c'est-à-dire celles qui peuvent être négatives) il se remplit de 1s pour les valeurs négatives, sinon des zéros.

1:

L'opérateur de décalage est essentiellement "mod" la largeur des données. Un int est 32 bits, donc un décalage à gauche de 33 (dans Int32) est exactement le même qu'un décalage à gauche de 1. Vous n'obtenez pas tous les zéros. Un long est 64 bits, donc un décalage à gauche de 33 donne une réponse différente (temps d'origine 2^33).

2:

Chaque décalage vers la gauche (dans la largeur de données) est le même (par des nombres entiers) sous la forme x2 - si < < 4 est x2x2x2x2 = x16.

C'est binaire simple:

0000000001 = 1 

< < va à

0000000010 = 2 

< < va à

0000000100 = 4 

< < va à

0000001000 = 8 
+0

Salut, puis-je vous demander de l'expliquer plus? Dans le premier pourquoi j'ai 0x200000000 et dans le second pourquoi j'ai 16000? merci beaucoup –

+0

C'est comme dire "pourquoi est 1 * 50000 différent de 1000 * 8" - parce que vous faites des choses très différentes. Le premier est 2^33 ("pouvoir de"), le second est 1000 * 16. –

+0

ok je comprends la différence entre 2^33 et 1000 * 16 je veux savoir pourquoi 2^32 –

6

Juste pour développer la réponse de Marc un peu (Marc, ne hésitez pas à inclure dans le vôtre et je vais supprimer cette réponse) cela est précisé dans la section 7.8 de la spécification:


Le opérateurs de décalage prédéfinis sont répertoriés ci-dessous.

décalage à gauche:

  • opérateur int < < (int x, int count);
  • Opérateur uint < < (uint x, nombre entier);
  • long opérateur < < (long x, nombre entier);
  • l'opérateur ulong (ulong x, compte int);

L'opérateur < < décale x à gauche d'un nombre de bits calculé comme décrit ci-dessous.

Les bits de poids fort en dehors de la plage du type résultat de x sont ignorés, les bits restants sont décalés vers la gauche et les bits binaires vides de poids faible sont mis à zéro.

Maj droite:

  • opérateur int >> (int count x, int);
  • Opérateur uint >> (uint x, nombre entier);
  • long opérateur >> (long x, nombre entier);
  • opérateur ulong >> (ulong x, nombre entier);

L'opérateur >> décale x à droite d'un nombre de bits calculé comme décrit ci-dessous. Lorsque x est de type int ou long, les bits de poids faible de x sont rejetés, les bits restants sont décalés vers la droite et les positions de bits vides de poids fort sont mises à zéro si x est non négatif et sont définies à un si x est négatif. Lorsque x est de type uint ou ulong, les bits de poids faible de x sont rejetés, les bits restants sont décalés vers la droite et les positions de bits vides de poids fort sont mises à zéro.

Pour les opérateurs prédéfinis, le nombre de bits de décalage est calculé comme suit:

Lorsque le type de x est un entier ou uint, le nombre de changement de vitesse est donnée par l'ordre faible cinq bits de comptage. En d'autres termes, le compte de décalage est calculé à partir du compte & 0x1F.

Lorsque le type de x est long ou ulong, le compte de décalage est donné par les six bits de poids faible. En d'autres termes, le compte de décalage est calculé à partir du compte & 0x3F.

Si le compte de décalage résultant est zéro, les opérateurs de décalage retournent simplement la valeur de x.


+0

J'apprécie votre aide. –

2

Quelques notes plus pour le programmeur débutant:

Pourquoi les opérateurs de changement d'utilisation? Ils ne semblent pas faire grand-chose. Eh bien, il y a 2 raisons:

  1. Ils sont très vite, parce que presque tous les processeurs ont des registres à décalage, ce qui signifie l'opération de déplacement se fait dans le matériel, la quantité minimum d'effort (cycles). Parce qu'ils sont rapides, beaucoup de protocoles et de normes sont conçus pour tirer parti de cela. Par exemple, opérations d'adresse IP, vérification d'un CRC, opérations graphiques, etc.

1

"L'opérateur de décalage est essentiellement" mod "la largeur des données."

Poubelle! Si la valeur du décalage est supérieure ou égale à la largeur des données, le résultat est indéfini. Ne vous attendez pas à ce que la même opération 'mod' que celle que vous avez vue se produise avec des compilateurs différents, ou des versions différentes du même compilateur, ou dans des situations de changement différentes dans le même programme, ou quand tout change. C'est ce que signifie "non défini".

+0

Actuellement, la spécification de langage C# 4.0 dit: 1) Lorsque le type de x est int ou uint, le décompte est donné par les cinq bits de poids les plus faibles. En d'autres termes, le nombre de changements est calculé à partir de count & 0x1F. 2) Lorsque le type de x est long ou ulong, le décompte est donné par les six bits de poids faible. En d'autres termes, le décompte est calculé à partir de count & 0x3F. – Ivan