2009-01-20 2 views
12

Я не могу понять этот оператор сдвига (C#):Поймите оператор сдвига

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 
*/ 

ответ

34

<< оператор сдвига влево; это берет двоичное представление значения и перемещает все биты «n» влево (за исключением «mod», см. «1»), заполняя нули нулями.

>> - оператор с правой стороны; это делает почти противоположное (перемещение вправо), за исключением подписанных значений (т. е. тех, которые могут быть отрицательными), он заполняет 1 с для отрицательных значений, а остальные нули.

1:

Оператор сдвига, по существу, «мод» ширина данных. Int - 32 бита, поэтому сдвиг влево 33 (в Int32) точно такой же, как сдвиг влево 1. Вы не получаете все нули. A long - 64 бит, поэтому сдвиг влево 33 дает другой ответ (исходное время 2^33).

2:

Каждый сдвиг влево (в пределах ширины данных) одно и то же (для целых чисел), как х2 - так < < 4 x2x2x2x2 = х16.

Это просто двоичный:

0000000001 = 1 

< < идет в

0000000010 = 2 

< < идет в

0000000100 = 4 

< < идет в

0000001000 = 8 
+0

Привет, могу я попросить вас объяснить это больше? В первом случае, почему у меня есть 0x200000000, а во втором - почему у меня 16000? Большое спасибо –

+0

Это как сказать «почему 1 * 50000 отличается от 1000 * 8» - потому что вы делаете совсем другие вещи. Первая - 2^33 («мощность»), вторая - 1000 * 16. –

+0

хорошо, я понимаю разницу между 2^33 и 1000 * 16 я хочу знать, почему 2^32 –

6

Просто расширить ответ Марка, немного (Марк, не стесняйтесь, чтобы включить это в ваших, и я удалю этот ответ) это указано в разделе 7.8 спецификации:


предопределенные операторы сдвига перечислены ниже.

Сдвиг влево:

  • INT оператор < < (целое х, INT счетчик);
  • Оператор uint < < (uint x, int count);
  • длинный оператор < < (long x, int count);
  • ulong operator < < (ulong x, int count);

< < Оператор смещает x слева на количество бит, вычисленное, как описано ниже.

Высшие разряды вне диапазона результата результата x отбрасываются, остальные бит сдвигаются влево, а разряды пустых разрядов младшего разряда устанавливаются на ноль.

сдвиг вправо:

  • ИНТ оператор >> (целое х, число целое);
  • uint operator >> (uint x, int count);
  • длинный оператор >> (long x, int count);
  • ulong operator >> (ulong x, int count);

Оператор >> сдвигает x справа на несколько бит, вычисленных, как описано ниже.

Когда x имеет тип int или long, младшие биты x отбрасываются, остальные бит сдвигаются вправо, а старшие разряды старшего разряда устанавливаются на ноль, если x неотрицательно и задано к одному, если х отрицательно.

Когда x имеет тип uint или ulong, младшие биты x отбрасываются, остальные биты сдвигаются вправо, а стартовые разряды старшего разряда устанавливаются на ноль.

Для предопределенных операторов, количество бит для сдвига вычисляется следующим образом:

Если типа х является INT или UINT, величина сдвига задается низким порядком пяти бит счетчика. Другими словами, подсчет сдвига вычисляется из числа & 0x1F.

Когда тип x длинный или улунгов, счетчик сдвига задается шестью битками младшего порядка. Другими словами, подсчет сдвига вычисляется из числа & 0x3F.

Если итоговое значение сдвига равно нулю, операторы сдвига просто возвращают значение x.


+0

Я привожу вашу помощь. –

2

еще несколько заметок для начинающего программиста:

Почему операторы используют сдвиг? Они, похоже, не очень много делают. Ну, есть 2 причины:

  1. Они очень быстро, потому что почти все процессоры имеют регистры сдвига, то есть операция не будет сделано в аппаратных средств, в минимальном количестве усилий (циклы).

  2. Поскольку они бывают быстрыми, для этого используются множество протоколов и стандартов. Например, операции с IP-адресом, проверка CRC, графические операции и т. Д.

1

«Оператор сдвига по существу является« mod »шириной данных».

Мусор! Если величина сдвига больше или равна ширине данных, результат не определен. Не ожидайте того же самого «мода», который вы видели, чтобы произойти с разными компиляторами или разными версиями одного и того же компилятора или в разных ситуациях смены в одной и той же программе или когда что-либо еще изменилось. Это то, что означает «неопределенный».

+0

актуальная спецификация языка C# 4.0 говорит: 1) Когда тип x является int или uint, счетчик сдвига задается младшими пятью битами счета. Другими словами, подсчет сдвига вычисляется из count & 0x1F. 2) Когда тип x длинный или ulong, счетчик сдвига задается шестью битками младшего порядка. Другими словами, подсчет сдвига вычисляется из count & 0x3F. – Ivan

Смежные вопросы