정적 타입 언어가 대부분 그렇듯 C#도 정수를 표현하는 여러 가지 타입을 제공하며, 타입마다 값의 범위가 달라요. 범위가 가장 작은 쪽부터 보면 sbyte 타입은 최솟값이 -128이고 최댓값이 127이에요. 모든 정수 타입과 마찬가지로 이 값들은 <type>.MinValue와 <type>.MaxValue로 확인할 수 있어요. 반대로 범위가 가장 큰 long 타입은 최솟값이 -9,223,372,036,854,775,808이고 최댓값이 9,223,372,036,854,775,807이에요. 그 사이에는 short와 int 타입이 있어요.
이 범위는 시스템이 타입에 할당하는 저장 크기로 정해져요. 예를 들어 byte는 8비트를, long은 64비트를 사용해요.
위의 타입들은 각각 부호 없는 타입과 짝을 이뤄요: sbyte/byte, short/ushort, int/uint, long/ulong. 어느 경우든 값의 범위는 0부터 부호 있는 타입의 음수 최댓값에 2를 곱하고 1을 더한 값까지예요.
| 타입 | 크기 | 최솟값 | 최댓값 |
|---|---|---|---|
| sbyte | 8 bit | -128 | +127 |
| short | 16 bit | -32_768 | +32_767 |
| int | 32 bit | -2_147_483_648 | +2_147_483_647 |
| long | 64 bit | -9_223_372_036_854_775_808 | +9_223_372_036_854_775_807 |
| byte | 8 bit | 0 | +255 |
| ushort | 16 bit | 0 | +65_535 |
| uint | 32 bit | 0 | +4_294_967_295 |
| ulong | 64 bit | 0 | +18_446_744_073_709_551_615 |
한 타입의 변수(또는 식)는 다른 타입으로 쉽게 변환할 수 있어요. 예를 들어 대입 연산에서, 대입되는 값의 타입(왼쪽, lhs)이 그 값이 대입되는 타입(오른쪽, rhs)의 범위 안에 확실히 들어간다면 단순한 대입으로 충분해요:
uint ui = uint.MaxValue;
ulong ul = ui; // no problem
반대로 대입되는 쪽 타입의 범위가 대입받는 쪽 범위의 부분집합이 아니라면, 특정 값이 그 범위 안에 들어가더라도 () 캐스트 연산이 필요해요:
short s = 42;
uint ui = (uint)s;
BitConverter 클래스는 정수 타입을 바이트 배열로, 또는 그 반대로 변환하는 편리한 방법을 제공해요.
무선 조종 자동차 프로젝트 작업이 계속되고 있어요. 텔레메트리 시스템의 대역폭이 매우 귀중한 상황이라, 텔레메트리 데이터를 주고받기 위한 메시지 프로토콜을 구현하라는 요청을 받았어요.
데이터는 버퍼(바이트 배열)로 전송돼요. 정수를 보낼 때는 아래에 설명된 프로토콜을 사용해 버퍼의 크기를 줄여요.
각 값은 가능한 한 가장 작은 정수 타입으로 표현해야 해요 (byte와 sbyte 타입은 절약되는 양이 미미해서 제외돼요):
| 부터 | 까지 | 타입 |
|---|---|---|
| 4_294_967_296 | 9_223_372_036_854_775_807 | long |
| 2_147_483_648 | 4_294_967_295 | uint |
| 65_536 | 2_147_483_647 | int |
| 0 | 65_535 | ushort |
| -32_768 | -1 | short |
| -2_147_483_648 | -32_769 | int |
| -9_223_372_036_854_775_808 | -2_147_483_649 | long |
값은 할당된 타입에 맞는 바이트 수로 변환해야 해요. 완전한 버퍼는 버퍼에 추가로 들어 있는 바이트 수를 나타내는 1바이트(프리픽스 바이트)와, 그 뒤에 정수를 담은 바이트들(페이로드 바이트)로 이루어져요.
일부 타입은 동일한 바이트 수를 사용해요 (예: uint와 int 타입). 보통은 같은 _프리픽스 바이트_를 가지겠지만, 그러면 디코딩에 문제가 생겨요. 이를 해결하기 위해 프로토콜은 작은 트릭을 도입해요. 부호 있는 타입의 경우 프리픽스 바이트 값은 256에서 버퍼에 추가된 바이트 수를 뺀 값이에요.
통신에서는 프리픽스 바이트와, 그것이 나타내는 수만큼의 뒤따르는 바이트만 전송돼요. 내부적으로는 송신과 수신 루틴 모두에서 (필요에 따라 뒤에 0을 채운) 9바이트 버퍼를 사용해요.
메서드에 전달된 매개변수를 받아 버퍼를 인코딩하는 정적 메서드 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 };
수신한 버퍼를 디코딩하고 값을 long 형태로 반환하는 정적 메서드 TelemetryBuffer.FromBuffer()를 구현해 보세요.
TelemetryBuffer.FromBuffer(new byte[] {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 })
// => 2147483647
프리픽스 바이트의 값이 예상 밖이라면 0을 반환해야 해요.
Exercism에 가입하고 C# 트랙을 개념 62개연습 문제 178개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.