C 프로그래머들의 가독성 범죄, IOCCC 대회 화제
세계 최대 규모의 난해한 C 코드 대회인 IOCCC(국제 난해 C 코드 대회) 2025년 결과가 발표되었습니다. 올해는 단 366바이트 크기의 코드로 에뮬레이터를 구현하여 리눅스를 구동하는 등 실질적인 활용 사례를 보여준 작품이 큰 화제를 모읍니다.
독특한 C 프로그래머들이 가독성에 대한 새로운 '범죄'를 저지르다. 어리둥절하고 홀릴 준비를 하라.
제29회 국제 난해 C 코드 대회(IOCCC)가 2025년 대회 결과와 함께 다시 돌아왔다. 올해 출품작 중 하나는 매우 독특한 새로운 비장의 무기를 선보였는데, 바로 '실제 활용 사례(valid use case)'이다. 지난해 이 행사가 4년 만에 부활했다는 소식을 전한 바 있기 때문에, 이렇게 빨리 다시 열린 것을 보니 매우 기쁘다.
글을 작성하는 현재, 심사는 약 3주 전에 마무리되었지만 유튜브에 업로드된 영상 길이가 거의 3시간에 달한다. 각 수상자별로 개별 클립을 편집하는 데 시간이 꽤 걸렸기 때문에 지금에서야 이를 다루게 되었다. 이 프로그램들 중 상당수는 실제로 어떤 동작을 하는지 직접 봐야 믿을 수 있을 정도이며, 평소에는 선호하는 포맷은 아니지만 이러한 목적에는 비디오 클립이 완벽하다.
올해는 무려 23개의 수상작이 있다. 여기에는 3연속 수상이라는 기록도 포함되어 있다: Yusuke Endoh, Nick Craig-Wood, Don Yang 세 명의 참가자가 각각 3개의 수상작을 거머쥐었다. 모든 작품을 소개할 지면은 부족하여 개인적으로 가장 돋보였던 몇 가지만 다루지만, 모든 수상작을 직접 읽어보기를 강력히 권장한다. 충분히 읽을 가치가 있다.
IOCCC의 특징 중 하나는 심사위원인 Landon Curt Noll과 Leonid A. Broukhis가 매년 각 수상작을 위해 새로운 부문을 창안한다는 것이다. 본문에서 그들의 부문 제목을 그대로 사용하기 때문에, 부제목이 처음에는 크게 와닿지 않더라도 해당 IOCCC 페이지를 읽어보면 모든 것이 명확해질 것이다(하지만 그것도 장담할 수는 없다).
IOCCC29 – 2025/cable – 최고의 가상 에뮬레이터(Best imaginary emulator)
우리가 지금까지 열린 모든 IOCCC의 결과를 빠짐없이 분석했다고 말할 수는 없다. 1984년 첫 대회가 열렸을 때, 이 기자는 아직 학교에 다니며 BASIC을 배우고 있었다. 하지만 올해 우리의 이목을 가장 많이 사로잡은 것은 Adrian Cable의 'Subleq 컴퓨터'였다.
그 이유는 우리가 이미 이것과 그것이 무엇을 하는지(또는 적어도 매우 밀접하게 관련된 프로젝트) 살펴보았기 때문이다. IOCCC 작품치고는 드물게도, 소프트웨어 보존이라는 실제 삶의 활용 사례를 가지고 있다.
영원한 소프트웨어 이니셔티브(ESI)의 아이디어는 매우 쉽게 에뮬레이션할 수 있도록 특별히 설계된 컴퓨터 아키텍처를 구현함으로써, 원래의 하드웨어 플랫폼이 더 이상 존재하지 않게 된 후에도 소프트웨어를 보존하는 데 도움을 주는 것이다. GitHub에 샘플 구현이 있다.
이 CPU 아키텍처는 새것이 아니다. 'Subleq'라고 불리는 단일 명령어 컴퓨터(OISC)다. OISC는 RISC의 논리적 외삽(최종 도달점)이다. 명령어 세트를 단 하나의 명령어까지 줄이는 것보다 더 이상 축소할 수 없기 때문이다. 이 경우 그 유일한 명령어는 'Subleq(0보다 작거나 같으면 빼고 분기)'이다. 2020년 설명에서도 이미 새로운 개념이 아니었으며, 2011년의 FPGA 하드웨어에서도 그 흔적을 찾을 수 있다.
ESI는 소프트웨어로 Subleq를 구현하고, LLVM을 사용하여 이를 타겟으로 하는 C 컴파일러를 구축했으며, C 및 C++ 런타임 라이브러리를 완비하여 리눅스를 이 아키텍처로 포팅했다. 이 리눅스에서 에뮬레이터를 실행하면 이 작은 기반 위에서 모든 하드웨어 아키텍처의 실행 가능한 버전을 부트스트랩(구동)할 수 있다.
여기서 말하는 '작다'는 것은 정말로 '아주 작다'는 뜻이다. 다음은 해당 아키텍처의 IOCCC 수상 구현 코드이다:
#include<SDL3/SDL.h> #define o s[1&s[t=e++]?s[t]/4:t]/4,t b,y,t e,s[3<<27],V[32],*w,**g;main(){for(g =SDL_GetWindowSurface(w=SDL_CreateWindow(0, 800,512,!read(b,s,'frog')));=o=y=o=o;~?~y ?e=1>(s[y]-=[s])?t:s&&++b>8e5?s[memcpy(3[ g],6[s]+s,25<<16),b=SDL_UpdateWindowSurface (w)]=4e,s/4:e:e:SDL_PollEvent(V)?y[s]=6[V ](1537-2**V):0)^64||timespec_get(s+,1);}
이게 전부다. 코드 길이는 단 366바이트에 불과하다. 그래픽을 표시하기 위해 SDL 라이브러리에 의존하는 것은 사실이지만, 그럼에도 불구하고 이것이 꽤 놀랍다는 데 동의할 것이라 믿는다. 시연 영상에서는 상당히 괜찮은 속도로 풀컬러 만델브로 집합을 생성한 뒤 퐁(Pong) 게임을 플레이하고, 이어서 Subleq에서 리눅스와 몇 가지 앱을 구동하는 모습을 보여준다.
이 영상을 볼 때, 이 소스 코드를 여백이 충분히 남는 엽서 뒷면에 직접 손으로 적을 수 있다는 사실을 꼭 기억해보라.