#C، مانند بسیاری از زبانهای ایستا، تعدادی نوع ارائه میدهد که اعداد صحیح را نمایش میدهند و هرکدام بازهی مقادیر خودش را دارد. در پایینترین حد، نوع sbyte حداقل مقدار -۱۲۸ و حداکثر مقدار ۱۲۷ را دارد. مانند همهی نوعهای صحیح، این مقادیر به شکل <type>.MinValue و <type>.MaxValue در دسترس هستند. در بالاترین حد، نوع long حداقل مقدار -۹,۲۲۳,۳۷۲,۰۳۶,۸۵۴,۷۷۵,۸۰۸ و حداکثر مقدار ۹,۲۲۳,۳۷۲,۰۳۶,۸۵۴,۷۷۵,۸۰۷ را دارد. در این میان، نوعهای short و int قرار دارند.
این بازهها بر اساس عرض ذخیرهسازیِ نوع که سیستم تخصیص میدهد، تعیین میشوند. برای مثال، یک byte از ۸ بیت و یک long از ۶۴ بیت استفاده میکند.
هر یک از نوعهای بالا با یک معادل بدون علامت جفت شده است: sbyte/byte، short/ushort، int/uint و long/ulong. در همهی موارد، بازهی مقادیر از ۰ تا منفیِ حداکثرِ علامتدار ضربدر ۲ بهعلاوهی ۱ است.
| نوع | عرض | حداقل | حداکثر |
|---|---|---|---|
| sbyte | ۸ بیت | -۱۲۸ | +۱۲۷ |
| short | ۱۶ بیت | -۳۲_۷۶۸ | +۳۲_۷۶۷ |
| int | ۳۲ بیت | -۲_۱۴۷_۴۸۳_۶۴۸ | +۲_۱۴۷_۴۸۳_۶۴۷ |
| long | ۶۴ بیت | -۹_۲۲۳_۳۷۲_۰۳۶_۸۵۴_۷۷۵_۸۰۸ | +۹_۲۲۳_۳۷۲_۰۳۶_۸۵۴_۷۷۵_۸۰۷ |
| byte | ۸ بیت | ۰ | +۲۵۵ |
| ushort | ۱۶ بیت | ۰ | +۶۵_۵۳۵ |
| uint | ۳۲ بیت | ۰ | +۴_۲۹۴_۹۶۷_۲۹۵ |
| ulong | ۶۴ بیت | ۰ | +۱۸_۴۴۶_۷۴۴_۰۷۳_۷۰۹_۵۵۱_۶۱۵ |
یک متغیر (یا عبارت) از یک نوع را میتوان بهسادگی به نوع دیگری تبدیل کرد. برای نمونه، در یک عملیات انتساب، اگر نوع مقداری که انتساب داده میشود (lhs) تضمین کند که مقدار در بازهی نوعی که به آن انتساب داده میشود (rhs) قرار میگیرد، آنگاه انتساب ساده است:
uint ui = uint.MaxValue;
ulong ul = ui; // no problem
از سوی دیگر، اگر بازهی نوعِ مبدأ زیرمجموعهای از بازهی مقادیر نوعِ مقصد نباشد، آنگاه حتی اگر مقدار خاص در بازهی مقصد قرار داشته باشد، به یک تبدیل نوع، یعنی عملگر ()، نیاز است:
short s = 42;
uint ui = (uint)s;
کلاس BitConverter روشی راحت برای تبدیل نوعهای صحیح به آرایههای بایت و برعکس فراهم میکند.
کار روی پروژهی ماشین کنترل از راه دور ادامه دارد. پهنای باند در سامانهی تلهمتری بسیار محدود است و از شما خواسته شده است که یک پروتکل پیام برای انتقال دادههای تلهمتری پیادهسازی کنید.
دادهها در یک بافر (آرایهی بایت) منتقل میشوند. هنگام ارسال اعداد صحیح، با بهکارگیری پروتکلی که در ادامه توضیح داده شده است، اندازهی بافر کاهش مییابد.
هر مقدار باید در کوچکترین نوع صحیح ممکن نمایش داده شود (انواع byte و sbyte لحاظ نشدهاند، چون صرفهجویی ناچیز خواهد بود):
| از | تا | نوع |
|---|---|---|
| ۴٬۲۹۴٬۹۶۷٬۲۹۶ | ۹٬۲۲۳٬۳۷۲٬۰۳۶٬۸۵۴٬۷۷۵٬۸۰۷ | long |
| ۲٬۱۴۷٬۴۸۳٬۶۴۸ | ۴٬۲۹۴٬۹۶۷٬۲۹۵ | uint |
| ۶۵٬۵۳۶ | ۲٬۱۴۷٬۴۸۳٬۶۴۷ | int |
| ۰ | ۶۵٬۵۳۵ | ushort |
| منفی ۳۲٬۷۶۸ | منفی ۱ | short |
| منفی ۲٬۱۴۷٬۴۸۳٬۶۴۸ | منفی ۳۲٬۷۶۹ | int |
| منفی ۹٬۲۲۳٬۳۷۲٬۰۳۶٬۸۵۴٬۷۷۵٬۸۰۸ | منفی ۲٬۱۴۷٬۴۸۳٬۶۴۹ | long |
مقدار باید به تعداد بایت مناسب برای نوع تخصیصیافتهاش تبدیل شود. بافر کامل شامل یک بایت است که شمار بایتهای اضافی در بافر را نشان میدهد (بایت پیشوند) و پس از آن بایتهایی قرار میگیرند که عدد صحیح را در خود دارند (بایتهای داده).
برخی از انواع از تعداد بایت یکسانی استفاده میکنند (مثلاً انواع uint و int). بهطور معمول، آنها بایت پیشوند یکسانی میداشتند، اما این کار رمزگشایی را دشوار میکرد. برای مقابله با این مشکل، پروتکل ترفند کوچکی به کار میبرد: برای انواع علامتدار، مقدار بایت پیشوند برابر است با 256 منهای شمار بایتهای اضافی در بافر.
در ارتباط، فقط بایت پیشوند و شمار بایتهای بعدی که با پیشوند مشخص میشوند فرستاده میشوند. در داخل، هم روالهای ارسال و هم روالهای دریافت از یک بافر ۹ بایتی استفاده میکنند (در صورت لزوم با صفرهای انتهایی).
لطفاً متد استاتیک TelemetryBuffer.ToBuffer() را پیادهسازی کنید تا با گرفتن پارامتری که به متد پاس داده میشود، یک بافر را رمزگذاری کند.
// Type: ushort, bytes: 2, signed: no, prefix byte: 2
TelemetryBuffer.ToBuffer(5)
// => {0x2, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
// Type: int, bytes: 4, signed: yes, prefix byte: 256 - 4
TelemetryBuffer.ToBuffer(Int32.MaxValue)
// => {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 };
لطفاً متد استاتیک TelemetryBuffer.FromBuffer() را پیادهسازی کنید تا بافر دریافتی را رمزگشایی کند و مقدار را به شکل یک long برگرداند.
TelemetryBuffer.FromBuffer(new byte[] {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 })
// => 2147483647
اگر مقدار بایت پیشوند غیرمنتظره باشد، باید 0 برگردانده شود.