▷ C/C++ 표준 데이터 타입과 그 크기를 보자. Windows MSVC(Visual Studio)로 빌드한 결과다.
- char (1byte)
- short (2byte)
- int (4byte)
- long (4byte)
▷ 무언가 어색하다. 왠지 흐름 상 long은 8byte여야 자연스러운데.. 이상하게도 long은 int와 똑같은 4byte다... int가 4byte라면, 이름이 암시하듯 long은 8byte가 되어야 하지 않을까? 왜 굳이 int와 똑같은 타입으로 해석한 것일까?
▷ 놀랍게도 리눅스에서 컴파일하면 long은 직관적으로 기대하듯이 8byte다. 플랫폼마다 C언어 표준의 해석이 다르다는 것도 난감하지만, Windows가 long과 int를 똑같이 해석한다는 것이 더 이상하다.
▷ 그 이유는 아래와 같다. 찾아보니 조금 황당했다.
▷ 이 정의는 윈도우 API 헤더 파일에 정의된 DWORD 변수에 대한 정의다. 윈도우즈는 오랫동안 이 정의를 바탕으로 윈도우즈 API를 개발했다. 32비트 데이터를 표현하는 DWORD는 64비트로 표준화된 오늘날의 컴퓨터에서도 가장 많이 사용되는 변수다. 그래서 DWORD도 윈도우즈 내부에서 굉장히 빈번하게 사용된다.
▷ 바로 위와 같은 이유로 long을 8byte라고 해석하지 못하는 것이다. DWORD가 long에 매핑되어 있는데, long을 64bit로 확장한 순간, 기존의 DWORD 매크로 정의를 사용하는 모든 소스코드의 의미가 완전히 무너진다. windows 기반의 프로그램이 뻗을 것이 분명하므로 long 타입을 8byte로 바꾸질 못하는 것이다. 만약 Windows가 long을 64bit라고 정의하고 컴파일러를 업데이트한다면 기존의 Windows API의 DWORD 정의를 싹다 바꿔야 한다. 헤더파일을 통해 DWORD를 long으로 간주하는 다른 응용 프로그램 소스코드도 변경이 불가피하다. 이런 이유로 쉽사리 long을 64bit로 전환할 수 없는 것이다.
▷ 그런데 다시 새로운 의문이 든다. 그렇다면 애초에 long 타입을 처음부터 8byte라고 하면 되지 않았을까? 말이다. 사실 여기에는 C 표준의 역사와 관련이 깊은 이유가 하나 있다.
▷ 원래 C언어의 표준 정수 데이터 타입은 char(8 bits), int(16 bits) 였다. 이때는 16비트 프로세서 시절이었고, C 표준은 int를 시스템에서 가장 쉽고 빠르게 처리할 수 있는 비트 수로 정의했었기에 int가 16bit로 정의되었다. 여기에 나중에 short(16 bits)와 long(32 bits)이 추가된 것이다. (이름을 보면 둘이 세트라는 것을 알 수 있다)
▷ 16비트 프로세서에서 32비트 프로세서로 넘어가던 과도기 시절에는 int가 표준이 지향하는 바에 맞게끔 16bit와 32bit로 다양하게 정의되었다. 그리고 나중에 64bit 프로세서가 대두되면서 C 표준에는 long long (64 bits) 타입이 추가되었고, 16비트 프로세서가 시장에서 사라지면서 int는 32bit로 굳어지게 되었다.
▷ 바로 여기서부터 유닉스/리눅스와 Windows가 long을 다르게 취급하기 시작했다. char는 8bit, short는 16bit, int는 32bit로 거의 굳어졌는데 과연 long을 어떻게 해석할 것인가? Unix가 long을 64bit로 교체한 와중에, Windows는 long을 32bit로 어쩔 수 없이 사용할 수 밖에 없었다. 왜냐하면 초창기 C표준이 int 타입을 시스템의 환경에 맞는 데이터 크기라고 정의하고 16bit로 지원하던 시점에서 Windows는 long을 32bit 크기로 '고정'된 무언가로 생각하고는, 이것을 DWORD로 정의하고 Windows API 개발에 수없이 많이 사용해왔던 것이다.
▷ 반면 Unix는 long을 32bit로 고정된 어떤 값이 아니라 포인터로 매핑한 오랜 역사가 있었고, 당연하게도 포인터는 64비트 시스템에서 64bit여야 하기 때문에 Unix는 long을 64bit로 교체하는 것이 자연스러운 흐름이었다.
▷ Windows는 당시 API에서 int를 16bit로 설계한 시점과 호환성을 따르다보니 long을 고정된 32bit 즉, DWORD로 매핑을 했고, 이후 꽤 많은 시간이 흐르면서도 수많은 API와의 호환성을 위해 long을 64bit로 업그레이드하지 못했던 것이다. int는 32bit가 되었는데도 말이다.
'IT 공부 > C, C++' 카테고리의 다른 글
[C/C++] - 크로스 플랫폼 오픈소스 라이브러리에서 OS 종속적인 부분은 어떻게? (공부 중...) (0) | 2025.01.01 |
---|---|
[C/C++] - int main() 함수에 extern "C" ?? (1) | 2024.12.31 |
[C/C++] - executable 파일에 dllexport를 쓸 수 있는가. (1) | 2024.12.31 |
[C언어] - 헤더 파일이 필요한 이유 (1) | 2024.12.27 |
[C언어] - C언어의 이식성에 대해 정리 (1) | 2024.12.26 |