운영체제(OS)에 독립적인 코드란, 프로그램이 실행되는 환경이 Windows든 Linux든 macOS든 상관없이 운영체제와 정상적으로 상호작용할 수 있는 프로그램을 의미합니다.
C/C++의 대부분의 컴파일러는 실행 환경의 운영체제를 감지할 수 있는 전처리기 매크로(predefined macros)를 제공합니다. 이 매크로들을 활용하면 컴파일 시점에 OS를 판별하고, 각 환경에 맞는 코드를 선택적으로 컴파일할 수 있습니다.
OS 감지에 사용되는 주요 매크로
GCC 컴파일러에서 자주 사용되는 대표적인 매크로는 다음과 같습니다.
- _WIN32 : 32비트 및 64비트 Windows 운영체제에서 정의됩니다.
- _WIN64 : 64비트 Windows 운영체제에서만 정의됩니다.
- __unix__ : UNIX 계열 운영체제(Linux 포함)에서 정의됩니다.
- __APPLE__ : macOS 환경에서 정의됩니다.
이처럼 컴파일러가 미리 정의해 두는 매크로를 조건부 컴파일 지시문(#ifdef, #else, #endif)과 함께 사용하면, 하나의 소스 코드로 여러 운영체제에서 동작하는 프로그램을 만들 수 있습니다.
예제 코드
아래 예제는 Windows에서는 dir 명령을, 그 외의 UNIX 계열 시스템에서는 ls 명령을 실행하여 디렉터리 목록을 출력하는 프로그램입니다.
#include <iostream>
using namespace std;
int main() {
#ifdef _WIN32
system("dir"); // Windows 환경
#else
system("ls"); // UNIX/Linux/macOS 환경
#endif
return 0;
}실행 결과
현재 디렉터리의 모든 파일 목록이 화면에 출력됩니다. (어떤 운영체제에서 실행하더라도 동일하게 동작)
코드 설명
#ifdef _WIN32는 해당 매크로가 정의되어 있는지 검사하는 전처리기 지시문입니다. Windows에서 컴파일하면 _WIN32가 정의되어 있으므로 system("dir")이 포함되고, 그렇지 않은 환경에서는 #else 블록의 system("ls")가 컴파일됩니다.
이 방식은 셸 명령뿐만 아니라 파일 경로 구분자(\와 /), 스레드 생성, 동적 라이브러리 로딩 등 운영체제마다 다른 API를 사용해야 하는 모든 상황에서 활용할 수 있습니다. 단, 플랫폼별 코드가 많아지면 유지보수가 복잡해질 수 있으므로, 가능하면 공통 인터페이스 뒤로 플랫폼 종속 코드를 숨기는 구조로 설계하는 것이 좋습니다.