기타 업적
C 언어
튜링상 선정 이유에는 포함되어 있지 않으나, 유닉스 하면 항상 따라붙는 것이 C 언어이다. 유닉스를 위해서 C 언어가 만들어졌고 C 언어 때문에 유닉스는 더욱 진화했다.
최초의 고급 프로그래밍 언어로 간주되는 포트란이 세상에 등장한 이래로 많은 프로그래밍 언어가 생겨났다. 지금도 새로운 언어들이 만들어지고 있다. 그 많은 언어들 중 강한 생명력을 보이는 언어 중 하나가 C 언어이다. C 언어는 객체지향언어인 C++이나 C#으로 분화되기도 했는데 C 언어뿐만 아니라 C++와 C#도 지금까지 큰 인기를 누리고 있다.
1970년대 초반에 만들어진 C 언어는 지금의 관점에서 보면 취약한 점이 많다. 특히나 보안이 취약하다는 평가를 받는다. 그 이유는 시스템 자원을 쉽게 직접 접근할 수 있게 해주기 때문이다. 대표적인 예가 포인터를 사용한 메모리 접근이다. 그런데 이것은 양날의 검과도 같다. 그 취약점 때문에 시스템 프로그래밍을 하기에 편하다. 그리고 컴파일된 코드의 효율이 매우 높다. 유명 요리사는 잘 벼려진 칼을 사용한다. 도구를 잘 다룰 줄 안다면 위험을 감수할 만하다.
역사
C 언어는 갑자기 하늘에서 뚝 떨어진 언어가 아니다. C라는 이름이 붙은 이유는, 이 언어가 B라는 언어에서 출발했기 때문이다. B 언어를 만든 이는 켄 톰슨이다. 그러면 B 언어는 A 언어에서 파생된 것일까? 그렇지는 않다. B 언어의 전신은 BCPL이었다.
1969년에 PDP-7 컴퓨터에서 최초의 유닉스가 동작하기 시작하자, 자연스럽게 이 컴퓨터에서 사용할 프로그래밍 언어에 대한 시도가 있었다. 그 시작은 더그 맥클로이Douglas Mcllroy가 이식한 TMG라는, 컴파일러용 언어이다. 원래 TMG는 1965년에 로버트 맥클루어Robert McClure가 개발했던 언어였는데 맥클로이는 멀틱스 프로젝트에서 TMG를 사용하여 PL/I 언어용 컴파일러를 개발해 본 경험이 있었다. 그래서 쉽게 PDP-7용 TMG에 도전할 수 있었는데 실제로 컴퓨터에서 실행되는 수준까지 개발한 것은 아니었고, 알고리듬 수준에서 완성했다. 그래서 사용하려면 손으로 알고리듬을 수행해야 했다.16
TMG를 보고 자극을 받은 켄 톰슨은 BCPL이라는 언어를 조금 고쳐서 PDP-7에서 사용하기로 마음먹는다. BCPL은 1960년대에 마틴 리처즈Martin Richards가 MIT에서 개발한 언어로 상당히 여러 곳에서 사용되었고 멀틱스 용으로도 이식되었다. 톰슨은 PDP-7 컴퓨터의 작은 메모리 용량 때문에 BCPL을 그대로 쓸 수 없었고 최대한 크기를 줄이려 노력했는데 그렇게 해서 만들어진 새로운 언어에 B라는 이름을 붙여주었다. B라는 이름을 붙인 이유는 BCPL을 간단히 줄인 것이라는 설이 유력하지만, 톰슨이 멀틱스 프로젝트 시절에 만들었던 Bon이라는 언어에서 비롯되었다는 설도 있다. Bon이라는 이름은 그의 부인 이름이기도 했다.16
B 언어는 인터프리터 방식이어서 매우 느리기는 했지만 PDP-7 컴퓨터에서 그 역할을 잘 수행했다. 하지만 PDP-11 컴퓨터로 넘어오면서 문제가 생겼다. PDP-7 컴퓨터는 워드word 기반으로 동작했다. 메모리의 한 주소에 저장되는 데이터의 크기가 18비트였다는 것이고, 마이크로프로세서 내에서의 연산도 18비트로 동작했다. 그런데 PDP-11 컴퓨터는 한 주소에 저장되는 데이터의 크기가 바이트, 즉 8비트였다. 그래서 B 언어로 작성한 프로그램이 효율적으로 동작하지 못했다.
1971년에 나는 B 언어에 문자형character type을 추가하면서 동시에 PDP-11 컴퓨터의 기계어가 결과물로 나오는 컴파일러를 만들기 시작했다… 나는 이렇게 살짝 확장된 언어에 NB라는 이름을 붙였다. New B, 즉 새로운 B 언어라는 의미였다.16
B와 BCPL은 모두 포인터를 다룰 수 있었다. 하지만 이 포인터가 메모리 주소를 직접 나타내는 것이 아니라, 행렬array의 인덱스index를 나타냈다. 인터프리터 방식으로 동작했으므로, 실행 과정에서 이 인덱스는 실제 주소값으로 변환되었는데 컴파일러 방식에서는 사용할 수 없는 방법이었다.
개념적으로 본다면 C 언어는 B 언어에 타입type 개념을 추가한 것이다. 데니스 리치는 정수int와 문자char 타입을 구별했고, 각각의 행렬과 포인터도 별도의 타입으로 간주했다. 아울러 구조체structure라는 복합 타입 개념이 도입되었는데, 이는 유닉스의 파일 테이블이나 프로세스 테이블 등을 구현하기 용이하게 해주기 위해서였다.5 이런 과정을 거치면서 B 언어와는 확연히 다른 모습을 가지게 된다.
타입을 정의하고 이와 관련된 문법을 만든 후에 컴파일러까지 구현하고 나니 NB라는 이름은 차이를 드러내기에 부족하다는 생각이 들었다. 나는 한 글자 스타일을 따르기로 마음먹었고 그래서 C라는 이름을 붙였다. C가 B의 다음 글자를 의미하는지, 아니면 BCPL에서 두 번째 C를 의미하는지는 독자의 상상에 맡기겠다.16
타입 개념 외에도 논리적 연산자인 &&와 || 가 추가되었고 #include나 #define과 같은 선처리기preprocessor가 도입되었다.
1973년 초가 되자 C 언어가 어느 정도 완성되었다. 그러자 본격적으로 유닉스 커널 시스템을 새롭게 C 언어로 작성하는 작업이 시작되었다. 아울러 IBM 360/370 시스템 등과 같이 다른 시스템을 위한 버전이 만들어졌으며 표준 입출력 라이브러리가 작성되었다.
1978년에 데니스 리치는 브라이언 커니핸과 함께 <C 프로그래밍 언어>17라는 책을 발표했다. 이 책은 프로그래머의 필독서 중 하나가 된다.
1973년 이후에도 C 언어는 조금씩 확장되었다. 이 과정에서 C 언어가 업체마다 조금씩 달라지는 문제가 발생했다. 1983년에 미국표준협회ANSI는 C 언어를 표준화하기 위한 위원회를 출범시켰고 1989년에 최종 표준안이 발표되었다.
데니스 리치는 C 언어의 성공을 다음과 같이 설명했다.
C 언어는 좀 별나면서 결함이 있지만 엄청난 성공을 거두었다. 분명히 역사의 우연성이 도움을 주기도 했겠지만 확실한 점은, 그것이 시스템 구현 언어가 가져야 할 요구사항을 만족시켰다는 것이다. 어셈블리어를 대체할 정도로 충분히 효율적이면서, 다양한 환경들에서 알고리듬과 상호작용을 기술하기에 충분한 추상성과 표현력을 가졌기 때문이다.16
특징
C 언어의 문법이나 특징을 굳이 여기에 세세히 포함할 필요는 없을 듯싶다. C 언어를 설명하는 많은 책과 자료들이 세상에 존재한다.
BCPL, B, C 언어는 알골 언어와 같이 프로시저procedure 방식의 언어이다. 명령어는 순차적으로 실행되며 대입문, 비교문, 반복문 등을 기본으로 한다. C로 작성된 프로그램 소스를 아주 높은 곳에서 바라본다면 그 구조는 단순하다. 그저 전역 변수 선언과 함수 선언의 집합이다. 본질적으로, 함수는 어느 곳에서든 호출될 수 있다는 점을 고려한다면 결국 전역 선언들의 집합인 셈이다.
C 언어로 프로그램을 짠다는 말은, 필요한 함수들을 구현한다는 말과 다름이 아니다.
답글 남기기