이식성 가이드

이식성 가이드 (Portability Guide)

D 언어를 여러 플랫폼에 걸쳐 쓸 때 생기는 이식성(portability) 문제를 최소화하는 방법을 다루는 챕터예요. 코드가 32비트와 64비트, 그리고 서로 다른 CPU 아키텍처에서도 올바르게 동작하도록 설계하는 데 꼭 필요한 내용을 정리해 봤어요.

출처: https://dlang.org/spec/portability.html

본문

코드에 불필요한(gratuitous) 이식성 문제가 생기는 것을 최소화하는 것은 좋은 소프트웨어 공학 관행이에요. 잠재적인 이식성 문제를 최소화하기 위한 기법들은 이러해요:

  • 정수형과 부동소수점형의 크기는 최솟값으로 간주하세요. 알고리즘은 타입의 크기가 커져도 계속 올바르게 동작하도록 설계해야 해요.

  • 부동소수점 계산은 실제 변수 크기가 담을 수 있는 것보다 더 높은 정밀도로 수행될 수 있어요. 부동소수점 알고리즘은 정밀도가 임의로 높아져도 계속 올바르게 동작해야 해요.

  • 컴파일러가 재배열(reorder)할 수 있는 계산에서 부작용(side effect)의 순서에 의존하지 마세요. 예를 들어:

a + b + c

이건 (a + b) + c, a + (b + c), (a + c) + b, (c + b) + a 등으로 평가될 수 있어요. 괄호는 연산자 우선순위(operator precedence)를 제어할 뿐, 평가 순서(order of evaluation)를 제어하지는 않아요.

결합(associative) 연산자 +*의 피연산자가 부동소수점 값이라면, 그 표현식은 재배열되지 않아요.

  • 바이트 순서(byte order)에 의존하지 마세요. 즉 CPU가 빅 엔디언(big-endian)인지 리틀 엔디언(little-endian)인지에 의존하지 말라는 뜻이에요.

  • 포인터나 참조(reference)의 크기가 특정 정수형과 같은 크기라는 점에 의존하지 마세요.

  • 크기 의존성이 어쩔 수 없이 생긴다면, 코드에 static assert를 넣어 검증하세요:

static assert(int.sizeof == (int*).sizeof);

32비트에서 64비트로의 이식성 (32 to 64 Bit Portability)

32비트 프로세서와 운영체제는 아직도 현장에 존재해요. 이를 염두에 두신다면:

  • 정수형의 크기는 32비트 코드와 64비트 코드 사이에서 동일하게 유지돼요.

  • 포인터와 객체 참조는 32비트 코드에서 64비트 코드로 넘어가면서 4바이트에서 8바이트로 커져요.

  • size_t를 주소 공간(address space)을 아우를 수 있는 부호 없는 정수형의 별칭(alias)으로 사용하세요. 배열 인덱스는 size_t 타입이어야 해요.

  • ptrdiff_t를 주소 공간을 아우를 수 있는 부호 있는 정수형의 별칭으로 사용하세요. 두 포인터 사이의 차이를 나타내는 타입은 ptrdiff_t 타입이어야 해요.

  • .length, .size, .sizeof, .offsetof, .alignof 프로퍼티는 size_t 타입이 돼요.

엔디언 (Endianness)

엔디언(endianness)은 다중 바이트(multibyte) 타입이 저장되는 순서를 말해요. 두 가지 주요 순서는 빅 엔디언(big endian)리틀 엔디언(little endian) 이에요. 컴파일러는 대상 시스템의 순서에 따라 버전 식별자 BigEndian 또는 LittleEndian을 미리 정의해요. x86 시스템은 전부 리틀 엔디언이에요.

엔디언이 중요해지는 경우는 이러해요:

  • 외부 소스(예: 파일)에서 다른 엔디언 형식으로 기록된 데이터를 읽을 때.
  • long이나 double 같은 다중 바이트 타입의 개별 바이트를 읽거나 쓸 때.

OS 관련 코드 (OS Specific Code)

시스템 특화 코드는 차이점을 별도의 모듈로 격리해서 처리해요. 컴파일 시점에 올바른 시스템 특화 모듈이 임포트되죠.

사소한 차이는 시스템 특화 임포트에 정의된 상수를 사용하고, 그 상수를 IfStatementStaticIfStatement에서 사용하는 방식으로 처리할 수 있어요.

더 알아보기 (Learn more)