مفهوم عملگر شیفت در #C
عملگر شیفت به سمت راست و یا <<، عددی را به تعداد بیت مشخص شده (x >> count)، به سمت راست منتقل میکند و دو نوع دارد:
الف) شیفت به راست منطقی
برای مثال اگر عدد 12 را به صورت باینری نمایش دهیم، به صورت زیر خواهد بود:
00000000 00000000 00000000 00001100
00000000 00000000 00000000 00000110
در این حالت همواره فرض میشود که عدد مدنظر، unsigned است.
ب) شیفت به راست ریاضی
شیفت به راست ریاضی، دقیقا مانند شیفت به راست منطقی است؛ مانند مثال زیر که عدد 1001 باینری را دو بیت به سمت راست منتقل میکند:
uint e = 0b_1001; Console.WriteLine($"Before: {Convert.ToString(e, toBase: 2),4}"); // Before: 1001 uint f = e >> 2; Console.WriteLine($"After: {Convert.ToString(f, toBase: 2).PadLeft(4, '0'),4}"); // After: 0010
برای مثال نمایش باینری عدد منفی 2,147,483,552- به صورت زیر است:
10000000 00000000 00000000 01100000
11111000 00000000 00000000 00000110
int x = -8; Console.WriteLine($"Before: {x,11}, hex: {x,8:x}, binary: {Convert.ToString(x, toBase: 2),32}"); // Before: -8, hex: fffffff8, binary: 11111111111111111111111111111000 int y = x >> 2; Console.WriteLine($"After >>: {y,11}, hex: {y,8:x}, binary: {Convert.ToString(y, toBase: 2),32}"); // After >>: -2, hex: fffffffe, binary: 11111111111111111111111111111110 int z = x >>> 2; Console.WriteLine($"After >>>: {z,11}, hex: {z,8:x}, binary: {Convert.ToString(z, toBase: 2).PadLeft(32, '0'),32}"); // After >>>: 1073741822, hex: 3ffffffe, binary: 00111111111111111111111111111110
سؤال: در زبان جاوا، عملگر <<< به معنای unsigned right shift است؛ اما چنین عملگری در زبان #C تا نگارش 11 آن وجود ندارد؛ چرا؟!
تا پیش از C# 11 اگر نیاز به کار بر روی signed types جهت رسیدن به نتیجهی عملگر <<< وجود داشته باشد (انجام شیفت منطقی؛ یعنی صرفنظر کردن از نوع علامت عدد)، میتوان از متدهای الحاقی زیر استفاده کرد که ابتدا آنها را به نمونههای unsigned تبدیل میکند و کار شیفت را انجام میدهد و سپس نوع اصلی را بازیابی میکند:
public static int UnsignedRightShift(this int signed, int places) { unchecked { var unsigned = (uint)signed; unsigned >>= places; return (int)unsigned; } } public static long UnsignedRightShift(this long signed, int places) { unchecked { var unsigned = (ulong)signed; unsigned >>= places; return (long)unsigned; } }