C++ 언어는 1980년대 초에 벨 연구소의 비얀 스트로스트룹(Bjarne Stroustrup)이 C언어를 기초로 하여 만들었다. C++ 은 C의 문법을 그대로 유지하면서 OOP(객체 지향 프로그래밍)기능을 추가하였다. 이 언어의 이름에 사용된 ++은 C언어의 증가 연산자를 의미하여 C보다 한 단계 더 발전했다는 뜻을 가지고 있다. C++의 OOP 문법은 Simula67이라는 언어의 문법을 참조하여 만들어진 것이다.

80년대 후반 소프트웨어가 하드웨어의 발전을 따라잡지 못하는 소프트웨어의 위기 문제가 대두되었으며 그 해결책으로 OOP가 제시되었다. 당시 C++은 소프트웨어 위기의 해결사로 인식되었으며 90년부터 본격적으로 사용되기 시작하여 지금은 대부분의 대형 프로젝트에 활용되고 있다. C++은 C언어에 비해 클래스, 상속, 다형성, 템플릿 등이 추가되었다. 이외에 기존 C언어로부터 물려받은 문법도 확장되었는데 다음은 대표적인 몇 가지 예이다.

① 한줄 주석은 //로 표기할 수 있다.

② 새로운 진위형인 bool 타입을 추가했다.

③ 구조체나 열거형의 태그 이름을 하나의 타입으로 인정한다.

④ 함수 중간에서 변수를 선언할 수 있다.

그렇다면 C와 C++ 두 언어의 관계는 과연 어떻게 정의될 수 있을까? 이 질문에 대해서는 학자에 따라 다양한 의견이 제시되고 있어 명확한 결론을 내리기 어렵다. C++이 C를 기반으로 하고 있고 C의 기능 대부분을 쓸 수 있으므로 C++이 C의 상위 버전이라는 주장이 있는 반면 C++이 C를 완전히 포함하지는 못하며 두 언어의 개발 방법이 워낙 판이하게 다르기 때문에 아예 다른 언어라고 보는 학자도 있다. 이 질문에 대한 해답은 각자가 공부를 마친 후 생각해 보기 바라되 나는 C++이 C의 상위 버전이며 그렇게 보는 것이 타당하다고 생각한다.

사용자 삽입 이미지

실제로 C의 문법 중 C++이 지원하지 못하는 부분도 있는데 이런 문법은 대부분 안정성, 이식성에 문제가 있거나 더 좋은 해결 방법이 있어 제외된 것들이다. 두 언어의 개발 방법이 다르다는 주장은 실제로 사실이며 문제 해결을 위한 접근 방법 자체가 다르다. 그러나 C++은 객체 지향한 지원하는 것이 아니라 C의 구조적 개발 방법도 여전히 지원하며 필요할 경우 C++로도 C 스타일의 프로그램을 작성할 수 있다. 구조적 프로그래밍 방법 객체 지향보다 열등하다고 생각하는 것도 일종 고정 관념일 뿐이며 필요하다면 쓸 수도 있다.
C++도 C와 마찬가지로 초창기에는 무분별한 기능 추가로 인해 호환성의 문제가 있었는데 90년대 초반의 볼랜드 C++과 비주얼 C++이 서로 호환되지 않았던 것이 대표적인 예이다. C++의 첫 번째 표준안인 ISO 14882는 98년에 발표되었다. 이 표준안은 89년에 제정된 ANSI C와 95년에 개정된 C95를 기반으로 하며 C++의 객체 지향적인 기능을 추가하여 작성된 것이다. 그래서 ANSI C의 기능 대부분을 흡수하고 있다. 그러나 시기적으로 1년 더 늦은 99년에 새로 제정된 C99 표준을 포함하지는 못하며 그래서 14882는 9899:1999와는 다소 다른면이 있다. 이후 C와 C++은 상호 영향을 미치며 서로 다른 모습으로 발전해 나갈 것으로 예상된다.
사용자 삽입 이미지
C를 쓸 것인가 C++을 쓸 것인가는 프로젝트의 성격에 따라 결정되어야 한다. 대부분의 경우 C++이 더 좋은 선택이 되겠지만 아직도 C가 필요한 경우는 여전히 있다. C++은 기능상 우위에 있기는 하지만 C보다 복잡하여 생성된 프로그램이 크고 느리기 때문에 소규모 프로젝트나 성능이 지극한 중요한 분야에는 적합하지 못한 면이 있기 때문이다. 가령 손목시계에 들어가는 프로그램이나 휴대용 게임기 등에는 객체를 쓰는 것이 어울리지 않으며 C가 더 좋은 선택이 된다. 닭 잡는데 소 잡는 칼을 쓸 필요는 없다.

그렇다면 이번에는 문제를 달리하여 지금 이 책을 읽는 사람은 C를 중심으로 공부를 할 것인가 아니면 C++을 중심으로 공부할 것인가를 생각해보자. 결론은 C++을 선택하는 것이 절대적으로 옳다는 것이다. 기능이 부족하다 하여 C를 무시하는 것은 좋지 않는 태도이지만 그렇다고 해서 C가 C++의 기반이므로 순수한 C를 먼저 배운후 C++을 나중에 배우겠다는 태토는 더 곤란하다. 주석은 무슨 일이 있어도 /* */로만 표기하고 변수는 반드시 함수 선두에만 선언해야 한다고 생각할 필요는 없다.

C++ 창시자인 스트로스트룹은 C++이 C의 모든 영역을 커버할 수 있다고 자신있게 떠들고 다닌다. 물론 학자들은 이 말에 절대적으로 공감하지 않으며 실제로 사실도 아니지만 적어도 그의 말이 99.9% 이상의 경우에 적용된다는데는 동의한다. 현재 출시되고 있는 컴파일러들은 대부분 C++ 컴파일러이며 C 전용 컴파일러는 구경하기가 쉽지 않다. 그래서 처음 C에 입문하는 사람들은 좋건 싫건 C++ 컴파일러로 시작할 수 밖에 없는 상황이다.

이 책은 98년에 발표된 ISO 14882를 기준으로 작성되어 있다. 저반부는 주로 C언어로부터 물려받은 문법들을 설명하여 중반 이후부터 C++의 고유 기능인 클래스를 다룬다. 전반부의 문법 설명 중에도 필요할 경우 C++ 문법이 가끔 등장하여 C의 문법과 비교하는 경우도 있다. 책의 구성이 C, C++로 이루어져 있는 것이 아니라 처음부터 C++ 문법을 다루되 객체 이전과 이후로 나누어져 있다는 점을 알아두기 바란다. 14882를 기준으로 하므로 C99의 확장된 문법 또는 그 이후에 개정되는 C 표준과 맞지 않는 면들이 있을 수 있다. 이런 점은 여러분들이 공부를 마친후 스스로 구분할 수 있을 것이다.

참고

C++은 "씨 플러스 플러스"(C plus plus)라고 읽도록 되어 있다. 그러나 이 발음이 너무 길어 불편하기 때문에 우리나라에서는 통상 "씨뿔뿔"이라고 읽는 경우가 훨씬 더 많다. 원문의 발음을 따르는 것도 좋겠지만 적어도 한글로 된 책에서는 표준보다는 현실적인 발음을 채택하는 것이 더 좋다고 생각하여 이 책에서는 "씨뿔뿔"로 읽기로 한다. 따라서 C++가, C++는, C++를 이라고 하지 않고 C++이, C++은, C++을 이라고 표기할 것이다.

Posted by 테티스
,

C언어는 1972년 벨 연구소의 데니스 리치(Dennis Ritchie)에 의해 만들어졌다. 데니스 리치는 UNIX 운영체제의 개발을 맡고 있었는데 운영체제는 그 특성상 하드웨어를 직접 제어할 수 있어야 했다. 또한 당시의 컴퓨터 환경이 지금과는 달라 CPU의 속도나 메모리의 용량이 충분하지 않았기 때문에 프로그램의 크기는 작아야 했고 속도는 빨라야했다.

이런 모든 요구를 만족시킬 수 있는 유일한 언어는 어셈블리밖에 없었다. 그러나 어셈블리는 특정 기계에 종속적이며 이식성이 없기 때문에 여러 플랫폼에 수정없이 사용하는 것이 목적인 UNIX와는 잘 어울리지 않았다. C언어보다 먼저 발표된 포트란이나 베이직같은 고급언어들은 효율이 좋지 못해 대형 프로젝트에 쓰기에는 역시 부적합했다.

그래서 데니스 리치는 기존의 언어를 사용하지 않고 어셈블리의 강력한 기능과 고급언어의 이식성을 동시에 갖춘 새로운 언어를 직접 만들었다. 물론 데니스 리치가 혼자서 C언어를 다 만든 것은 아니며 과거 언어들의 장점을 취합 정리해서 만든 것이다. C언어의 뿌리는 최초의 구조적 언어인 ALGOL이며 데니스 리치는 동료인 켄 톰슨(Ken Thompson)이 만든 B언어를 개량하여 C언어를 만들었다. C언어의 계보를 그려 보면 다음과 같다.

사용자 삽입 이미지

이 언어에 C라는 이름을 붙인 이유는 단순히 B보다 한단계 더 발전했다는 의미로 B 다음의 알파벳인 C를 사용한 것이다. 그래서 혹자는 C언어 다음은 D언어가 나올 것이다라고 얘기하기도 하는데 이런 예상과는 달리 C언어의 다음은 C++이 되었다. C언어는 간결하면서도 강력한 프로그램을 작성하기에 적합하여 오늘날 가장 대중적인 프로그래밍 언어로 사용되고 있다.

C언어가 발표되기 전의 언어들은 각각 장단점이 있어서 특정 분야에서 독점적인 지위를 가지는 고유의 영역을 확보하고 있었다. 예를 들어 파스칼이나 베이직은 교육용 언어로 분류되었고 코볼은 상업용 소프트웨어 작성에 효율적이었으며 포트란은 과학 기술용 언어로 주로 사용되었다. 또한 리스프는 인공 지능 구현에 적합했으며 어셈블리는 시스템 프로그래밍을 위한 최적의 언어였다. 그러나 이런 분류는 모든 분야에 강점을 보이는 범용의 C언어가 등장함으로써 의미를 잃게 되었다. C언어가 모든 분야를 제압해 버린 것이다.

C언어는 그 강력함으로 인해 80년대 이후 여러 분야에 걸쳐 광범위하게 사용되기 시작했으며 가장 인기있는 언어가 되었다. 그러나 데니스 리치가 처음 C언어를 디자인할 때에 비해 컴퓨터 환경이 많이 변해 비효율적인 면들이 점점 드러나기 시작했으며 또한 애매한 문법들이 존재했었다.

각 컴파일러 개발사들은 경쟁적으로 수많은 C컴파일러를 발표했다. 컴파일러는 일종의 상품이기 때문에 타사 제품과 차별화되는 기능이 있어야 하고 변화된 환경에 적응할 수 있는 새로운 기능을 추가할 필요도 있다. 각 제작사들은 시장의 요구와 필요에 따라 조금씩 언어의 기능을 확장함으로써 C언어에도 많은 변종들이 생겨나게 되었다. 이렇게 되면 작성한 컴파일러에 따라 소스 차원의 호환성이 없어지는 문제점이 있으며 이는 사회적으로 큰 낭비를 초래하였다.

변화된 환경에 적응하고 경쟁으로 인해 훼손된 이식성을 복구하기 위해서는 표준의 제정이 절실히 필요해졌다. 그래서 미 표준 위원회인 ANSI는 83년부터 표준 제정 작업에 들어가 89년에 표준안을 완성했으며 90년에 ISO에 의해 승인(ISO 9899)되었다. 이때 제정된 C 표준을 ANSI C(또는 C90)라고 하며 그 이전의 C를 클래식 C(K&R C)라고 한다. ANSI C는 클래식 C에 비해 안전성을 높이고 애매한 기능을 정리하였으며 다음과 같은 기능을 추가했다.

 

표준 라이브러리 함수를 규격화했으며 헤더 파일도 통일했다.

함수의 원형 선언 기능이 추가되어 컴파일러가 함수 호출부에서 타입 체크를 할 수 있다.

정수, 실수 상수의 타입을 지정할 수 있는 L, U, F 등의 접미어가 추가되었다.

enum, void 형과 const, volatile 제한자가 추가되었다.

인접 문자열 상수를 합쳐 주고 확장열의 기능도 추가되었다.

함수 내부에서 선언하는 지역 배열이나 구조체를 초기화할 수 있다.

구조체끼리 대입할 경우 구조체 크기만큼 메모리 복사를 한다.

 

이후에도 C표준은 지속적으로 확장되었는데 95년에 유럽과 동양의 언어를 지원하기 위한 멀티 바이트 문자 지원이 추가되었다. 이때 제정된 C 표준을 C95라고 하는데 ANSI C에 비해 언어의 기능상 큰 변화는 없었다. 그리고 99년에 다양한 기능을 추가하고 C++의 장점을 흡수하여 다시 한 번 개정되었으며 2005년 경에 또 한 번 더 개정될 예정이다. 그러나 실제 여러분들이 사용할 C++은 ANSI C를 기준으로 하기 때문에 그 이후에 C문법에 대해서는 당분간 관심을 두지 않아도 될 듯 하다.

Posted by 테티스
,

컴퓨터에게 일을 시키려면 컴퓨터와 사람간의 의사소통 도구가 필요하다. 사람이 무엇을 원한다는 것을 어떤 형태로든지 컴퓨터에게 알려 주어야 하는데 이것이 바로 프로그래밍 언어이다. 사람끼리의 대화에도 언어가 필요한 것처럼 컴퓨터와 사람 사이에도 명령을 전달하고 결과를 보고받을 수 있는 언어가 필요하다. 프로그래밍 언어도 의사 소통을 위한 도구라는 면에서 언어의 사전적 정의와 일치하되 다만 대화상대가 사람이 아니라 기계라는 점만 다를 뿐이다.

컴퓨터는 사람이 사용하는 자연어를 이해하지 못한다. 계산하라, 출력하라와 같은 말로 된 명령은 컴퓨터라는 단순한 기계에게는 너무 어렵고 때로는 모호하기도 해서 해석할 수가 없다. 컴퓨터는 수많은 스위치들로 구성되어 있으며 스위치에 전기가 통하는가 그렇지 않은가의 두 가지 상태밖에 구분하지 못한다. 전기의 흐름, 차단 상태를 숫자로 표기하면 이진수가 되는데 이진수는 컴퓨터가 이해하는 유일한 언어이다.

그래서 컴퓨터가 어떤 연산을 하도록 하려면 이진수로 된 기계어 명령을 전달해야만 한다. 실제로 초창기의 프로그래머들은 컴퓨터에 붙어있는 스위치를 올렸다 내렸다 하면서 이진수로 된 기계어 코드를 작성해야만 했다. 그러나 1과 0으로만 구성되어 있는 이진수는 도저히 인간의 생리와는 맞지 않은 언어이다. 그래서 좀 더 쓰기 쉬운 자연어와 유사한 프로그래밍 언어를 만들게 되었다.

사용자 삽입 이미지

프로그래머는 기계어 코드를 모르더라도 언어의 문법과 형식에 맞게 명령을 작성하면 된다. 이 명령은 컴파일러라고 부르는 중간의 번역 프로그램에 의해 기계어로 변환되며 컴퓨터는 이렇게 변환된 기계어를 실행하는 것이다.

그동안 셀 수 없을 정도로 많은 프로그래밍 언어가 개발되었다. 포트란으로부터 시작하여 코볼, 베이직, 알골 등을 거쳐 C, 파스칼과 최근의 자바, C#까지 헤아릴 수 없이 많은 종류가 있다. 자연어에도 한국어, 영어, 불어, 중국어 등의 각종 언어들이 있듯이 말이다. 각 언어들은 나름대로의 장점과 단점을 가지는데 프로그래머는 이 중 자신의 목적에 맞는 언어를 선택해야 한다. 프로그래밍 언어는 여러 가지 방법으로 분류할 수 있지만 인간과 얼마나 가까운가에 따라 수준(Level)을 분류한다.

 

저급 언어(Low Level) : 기계의 언어에 가까우며 사용하기는 어렵지만 성능은 좋다. 대표적으로 어셈블리가 있다.

고급 언어(High Level) : 인간의 언어에 가까우며 배우기 쉽지만 대신 성능은 떨어진다. 베이직 언어가 대표적인 고급 언어이다.

 

저급이라고 해서 성능이나 효율이 떨어진다는 뜻은 아니며 고급이라고 해서 모든 것이 좋다는 뜻도 아니다. 이 분류 방법은 다만 인간의 입장에서 볼 때 얼마나 배우기 쉽고 쓰기 쉬운가를 기준으로 할 뿐이다. 이 책에서 다루는C/C++언어는 분류상 고급 언어에 속한다. 그러나 섬세한 하드웨어 제어가 가능하기 때문에 중급 언어로 분류하기도 한다.

Posted by 테티스
,