2.3 Comments

 우리의 pun.c 프로그램은 아직 부족하다. 바로 문서화이다. 모든 프로그램에는 프로그램 이름, 작성된 날짜, 작성자, 프로그램의 목적 등 식별 정보가 포함되어야 한다. C에서 이 정보는 주석에 배치하면 된다. 기호 /*는 주석의 시작부분을 표시하고 기호 */는 끝부분을 표시한다.

*/ This is a comment */

 주석은 프로그램의 거의 모든곳에서 별도의 행이나 다른 프로그램 텍스트와 같은 행에 나타낼 수 있다. pun.c의 시작부분에는 다음과 같이 주석을 쓸 수 있다.

/* Name: pun.c                 */
/* Purpose: Prints a bad pun.  */
/* Author: K. N. King          */

#include <stdio.h>

int main(void)
{
    printf("To C or not to C: that is the question.\n");
    return 0;
}

 주석은 둘 이상의 줄에 걸쳐 확장할 수 있다. 컴파일러가 /*기호를 확인한 후 */기호를 만날때 까지는 이어지는 내용을 읽고 무시한다. 위 주석을 다음과 같이 짧게 만들 수 있다.

/* Name: pun.c                
   Purpose: Prints a bad pun.  
   Author: K. N. King          */

 하지만, 가독성이 떨어지기 때문에 권하지는 않는다. 차라리 다음과 같이 하면 도움이 된다.

/* Name: pun.c                
   Purpose: Prints a bad pun.  
   Author: K. N. King     
*/

더 좋은 방식의 주석은, 다음처럼 박스로 만드는 것이다.

/*************************************
 * Name: pun.c                       *
 * Purpose: Prints a bad pun.        *
 * Author: K. N. King                * 
 *************************************/

가끔씩 박스형 주석을 단순화 시키는 프로그래머들도 있다.

/*
 * Name: pun.c 
 * Purpose: Prints a bad pun. 
 * Author: K. N. King 
 */

짧은 주석은 프로그램 코드와 같은 줄에도 표시될 수 있다.

int main(void)  /*Beginning of main program*/

이런 주석을 날개형 주석이라고도 부른다.

C99부터는 다음과 같은 주석을 제공한다.

//This is a comment

이런 주석 유형은 줄 끝에서 자동으로 끝난다. 두줄 이상의 주석을 만드려면 이전 버전 주석(/**/)을 사용하거나 각 주석의 줄 시작부분에 넣으면 된다.

// Name: pun.c
// Purpose: Prints a bad pun.
// Author: K. N. King

새로운 주석 스타일은 두가지 중요한 점이 있는데, 첫번째로 코멘트가 자동으로 줄의 끝에서 끝나기 때문에 종료되지 않은 주석이 프로그램의 일부를 실수로 가릴 가능성이 없다. 두번째로, 각 줄에 요구되는 // 덕분에 긴 줄의 주석이 돋보인다.

2.2 The General Form of a Simple Program

pun.c에 대해서 깊게 알아보고, 이것을 일반화시켜보는 단원이다. C에는 다음과 같은 형식이 있다.

directives (전처리문)

int main(void)
{
  statements (명령문)
}

이 템플릿에서, 그리고 이 책의 다른곳에서 있는 유사한 템플릿에서는 Courier 체로 인쇄된 항목은 C 프로그램에서 보여준대로 정확히 등장해야하는 부분이다. Italics 체로 인쇄된 항목의 경우 프로그래머가 제공하는 텍스트를 나타낸다. (티스토리에서는 코드블록 사용시 폰트 적용이 안되기에, 필요한 경우 책을 참고하길 바란다.)

중괄호가 main 시작지점과 끝지점을 표시하는 방법에 주의해라. 다른 언어들이 begin 이나 end 를 쓰는 것처럼 C는 { 와 }를 사용한다. 이런 점에서 C에대한 일반적인 부분을 설명할 수 있다. 바로, C프로그램은 간결성 때문에 약어와 특수 기호에 크게 의존한다는 것이다. 

가장 간단한 C 프로그램도 다음 세가지 핵심 언어 기능에 의존한다. 전처리문(컴파일 전에 프로그램을 수정하는 명령 편집), 함수( main처럼 실행 가능한 코드의 함수명이 지어진 블록), 명령문(프로그램이 실행될 때 수행할 명령)

Directives 전처리문

C 프로그램은 컴파일되기 전에 전처리기에 의해 편집된다. 전처리기의 명령어를 전처리문이라고 한다. 14, 15장에서 깊게 배우겠지만, 지금은 #include 에 대해서만 배운다. pun.c 프로그램은 다음처럼 시작된다.

#include <stdio.h>

이 지시문은 <stdio.h>의 정보가 프로그램이 컴파일 되기 전에 포함됨을 명시한다. <stdio.h>에는 C의 표준입출력에 대한 정보가 포함되어있다. C는 <stdio.h>와 같은 헤더파일이 많은데 이는 각각 표준 라이브러리의 일부를 포함하고 있다. C에서 <stdio.h>를 포함해야하는 이유는, 다른 프로그래밍언어와는 다르게, '읽고 쓰는' 명령어가 내재되어있지 않기 때문이다. 대신, 입출력을 수행하도록 하는 능력은 표준라이브러리의 기능에 제공된다.

전처리문은 항상 C프로그램의 다른 항목과 구별되는 # 문자로 시작한다. 기본적으로 전처리문은 한줄 길이이며 전처리문 끝에는 세미콜론이나 다른 특수 문자가 없다.

Functions 함수

함수는 다른 프로그래밍 언어의 'procedures'나 'subroutines'와 같다. 그것들은 프로그램을 구성하는 블록을 쌓는 것이다. 사실상 C프로그램이 더 함수의 종류가 많다. 함수는 두 종류로 나뉘는데, 프로그래머가 직접쓴것과, C도구로 제공되는 것이다. 나중에 라이브러리 함수에서 언급하겠지만, '라이브러리'에 속해있는 함수이기때문에 컴파일러를 지원한다. 

 수학에서, 하나 이상의 인수가 주어졌을때 값을 계산하기 위한 규칙인 함수에서 이름을 따왔다.

C는 함수라는 용어를 더 확장시켰다. C에서 함수는 단순하게 "함께 그룹화되어 이름이 지정된 일련의 명령문"이다. 어떤 함수는 값을 계산하지만, 그렇지 않은 함수도 있다. 값을 계산하는 함수는 반환문을 사용하여 리턴값을 지정한다. 예를 들어 인수에 1을 더하는 함수는 다음과 같은 문장이 나온다.

return x+1;

서로 다른 인수의 제곱의 차를 계산하는 함수는 다음과 같은 문장으로 쓸 수 있다.

return y*y-z*z;

C 프로그램은 많은 함수로 구성될 수 있지만, main함수는 필수적으로 필요하다. main함수는 특별한데, 프로그램이 실행될 때 자동으로 호출된다는 점이다. 다른 함수에 대해 배우는 9장 전까지는 main함수가 프로그램에서 유일한 함수가 될것이다. 

main함수의 경우, 값을 반환하는가? 그렇다. 프로그램이 종료될 때 운영체제에 제공된 상태코드를 반환한다. pun.c 프로그램에서의 경우를 보자.

#include <stdio.h>

int main(void)
{
    printf("To C or not to C: that is the question.\n");
    return 0;
}

main함수 바로 앖의 int는 main함수가 정수값을 반환함을 뜻한다. 괄호 안의 void는 main에 인수가 없음을 뜻한다.

return 0;이란 문장은 두가지 기능이 있다. 프로그램을 종료하기 위해 main함수가 종료되도록 하고, main함수의 값이 0이 반환됨을 지시해준다. 나중에 main의 리턴값에 대해 알아보겠지만, 지금은 main은 프로그램을 종료하기 위해 항상 0을 리턴한다고 생각하자.

Statements 문장

문장은 프로그램이 동작할 때의 실행할 명령이다. 이 책의 5, 6장에서 자세히 살펴볼것이다. pun.c 프로그램은 딱 두종류의 문장을 사용하는데, 하나는 리턴문이고, 하나는 함수 호출이다. 할당된 작업을 수행하기 위해 함수를 요청하는 것은 함수 호출이라고 한다. 예를 들어 pun.c 프로그램은 printf함수를 호출하여 화면에 문자열을 표시한다.

printf("To C or not to C: that is the question.\n");

C는 각 문장이 세미콜론으로 끝나도록 요구한다. (단, 복합문에서는 예외이다.) 세미콜론은 컴퓨터에게 문장이 끝나는 점을 보여주기에 문장은 여러 줄에 걸쳐 작성해도 항상 끝나는 지점이 명백하다. 반면 전처리문은 한줄을 기본으로 쓰며, 세미콜론을 사용하지 않는다.

Printing Strings 문자열 출력

printf는 3장에서도 보겠지만, 강력한 함수이다. 지금까지는 큰따옴표로 묶인 문자열상수를 표시하는데만 printf를 사용했다. printf는 문자열 상수를 표시할 때 큰따옴표까지 화면에 보여주지는 않는다.

한번 출력이 되면, 다음 출력라인으로 자동으로 이동하지 않는다. printf에 한줄을 띄우도록 지시하려면 출력할 문자열에 \n(개행 문자)를 포함해야 한다. 개행문자를 작성하면 현재 출력하는 줄이 종료되고 다음 출력은 다음줄로 이동한다. 따라서 다음 두 코드는 같은 결과를 표시한다.

printf("To C or not to C: that is the question.\n");

printf("To C or not to C: ");
printf("that is the question.\n");

개행 문자는 문자열상수에 두번 이상 나타날 수 있는데, 다음 메세지를 코드로 작성하면 그다음과 같다.

Brevity is the soul of wit.
  --Shakespeare
printf("Brevity is the soul of wit.\n --Shakespeare\n);
"One man's constant is another man's variable"
'누군가의 상수는 다른사람의 변수이다.'
– 앨런 펄리스(Alan J. Perlis)

이번 장에서는 최소한의 문법인 전처리기 지시문, 함수, 변수 및 statement를 포함한 몇 가지 기본 개념을 다룬다. 2.1에서는 간단한 C 프로그램을 제공하고 컴파일 및 링크하는 방법을 설명한다. 2.2에서는 프로그램을 일반화하는 방법에 대해 배우고, 2.3에서는 주석을 추가하는 방법을 보여줄 것이다. 2.4에서는 프로그램 실행중 변경될 수 있는 데이터를 저장하는 '변수'에 대해 소개하며, 2.5에서는 scanf 기능을 사용하여 데이터를 변수로 읽는 방법이 있다. 2.6에서는 프로그램 실행 중에 변경되지 않는 상수에 이름을 부여하는 것을 배우고, 2.7에서는 이름(식별자)를 만드는 C의 규칙을 설명하며, 2.8에서는 프로그램을 배치하기 위한 규칙을 제공한다.

2.1 Writing a Simple Program

다른 언어로 쓰인 프로그램과 달리, C 프로그램에는 "표준 문안"이 거의 필요하지 않으며 완전한 프로그램은 몇 줄밖에 안나올 정도로 짧을 수 있다.

Printing a Pun

Kernighan과 Ritchie의 고전, K&R책의 첫번째 프로그램은 매우 짧다. 바로 "hello, world"라는 단어를 쓰는 것이다. 그러나, 이 책에서는 다른 C프로그램 책 작가들과 달리 C의 고전 말장난을 사용할 것이다.

To C or not to C : that is the question.

다음 프로그램을 우리는 pun.c라고 부를 것이다.

#include <stdio.h>

int main(void)
{
    printf("To C or not to C: that is the question.\n");
    return 0;
}

2.2에서 더 자세히 다루겠지만, 우선 우리는 몇가지만 보기로 한다.

#include <stdio.h> 라는 문장은 C의 표준입출력 라이브러리에 대한 정보를 '포함'하는데 필요하다. 프로그램의 실행 가능한 코드는 메인 프로그램을 나타내는 main 내부에 들어간다. main 안의 코드는 원하는 메세지를 표시하게 하는 명령이다. printf는 표준입출력 라이브러리에서 제공하는 기능이며, 형식대로 출력을 할 수 있게 해준다. \n(백슬래시n)코드는 메세지를 출력한 후 다음 행으로 이동하도록 printf에게 지시하는 코드이다. 마지막의 return 0;은 프로그램이 종료될때 0값을 운영체제에 '반환'함을 나타낸다.

Compiling and Linking

짧은 내용임에도 pun.c를 동작하는 것은 생각보다 많은 것이 포함되어 있다.

먼저, 우리는 pun.c 라는 이름의 파일을 생성해야 한다. 파일의 이름은 중요하지 않지만, .c 확장자는 종종 컴파일러들에게 요구된다. 그리고 프로그램을 기계가 실행할 수 있는 형태로 변환해야 하는데, C프로그램의 경우 일반적으로 다음 세단계를 포함한다.

  • 전처리기. 프로그램은 먼저 지시라고 알려진 #으로 시작하는 명령을 전처리기에게 제공해야한다. 전처리기는 에디터와 비슷한데, 프로그램에 뭔가를 추가하고 수정할 수 있다.
  • 컴파일링. 수정된 프로그램은 이제 컴파일러로 이동하며, 컴파일러는 이를 기계명령(개체코드)으로 변환한다. 그러나 이 프로그램은 아직 실행준비가 되어있지 않은 상태이다.
  • 링킹. 마지막 단계에서 링커는 컴파일러에 의해 생성된 객체코드와 완전히 실행 가능한 프로그램을 만들어내는데 필요한 추가 코드를 결합한다. 이 추가 코드는 프로그램에서 사용되는 라이브러리 함수(ex: printf)를 포함한다.

다행히, 이 프로세스는 자동화되어있고, 보통 컴파일러와 통합되기 때문에 부담을 가지지 않아도 된다. 컴파일 및 링크에 필요한 명령은 컴파일러와 운영체제에 따라 다르다.  UNIX 아래에서 C컴파일러는 보통 cc로 이름이 붙는다. pun.c 프로그램을 컴파일하고 연결하기 위해 터미널 혹은 명령줄 창에 다음 명령을 입력한다.

%cc pun.c

(%는 UNIX 프롬프트이며, 입력하지 않아도 된다.) 링크는 cc를 사용할때 자동으로 수행되므로 별도의 링크 명령이 필요없다. 프로그램을 컴파일하고 연결한 후, cc는 실행 가능한 프로그램을 기본적으로 a.out이라는 파일에 남겨둔다. cc에는 여러 옵션이 있는데 그중 하나 -o옵션을 사용하면 실행 가능한 프로그램이 포함된 파일 이름을 선택할 수 있다. 예를 들어, pun.c의 실행 가능한 버전을 pun으로 명명하려면 다음명령을 입력한다.

%cc -o pun pun.c

가장 유명한 C컴파일러는 GCC 컴파일러인데, 이는 리눅스와 함께 제공되며, 많은 플랫폼에서도 사용가능하다. 이 컴파일러 사용법은 전통적인 UNIX CC 컴파일러를 사용하는 것과 유사하다. pun.c프로그램을 컴파일 하기 위해서는 다음과 같이 명령한다.

%gcc -o pun pun.c

Integrated Development Environment

IDE, 즉 통합개발환경에 대한 이야기이다. 지금까지는 운영체제에서 제공하는 특수 창에 명령을 입력하여 호출되는 "명령줄"컴파일러를 사용하는 것으로 가정했다. 대안책으로 IDE를 사용할 수 있는데, 이는 상태를 바꾸지 않고도 프로그램을 편집, 컴파일, 링크, 실행 및 디버그 할 수 있는 소프트웨어 패키지이다. IDE의 구성요소는 함께 작동할 수 있도록 설계되었다. 예를 들어 컴파일러가 프로그램에서 오류를 감지하면 에디터가 오류를 포함하는 줄을 강조하도록 정렬할 수 있다. 

 

목차는 다음과 같다.

  • 2.1 Writing a Simple Program
    • Program: Printing a Pun
    • Compiling and Linking
    • Integrated Development Environments
  • 2.2 The General Form of a Simple Program
    • Directives
    • Functions 
    • Statements
    • Printing Strings
  • 2.3 Comments
  • 2.4 Variables and Assignment
    • Types
    • Declarations
    • Assignment
    • Printing the Value of a Variable
    • Program: Computing the Dimensional Weight of a Box
    • Initialization
    • Printing Expressions
  • 2.5 Reading Input
    • Program: Computing the Dimensional Weight of a Box(Revisited)
  • 2.6 Defining Names for Constants
    • Program: Converting from Fahrenheit to Celsius
  • 2.7 Identifiers
    • Keywords
  • 2.8 Layout of a C Program

이번 장에서는 드디어 C의 문법을 들어가는 듯 싶다. 목차에 Program: 이 붙은 주제는 소스코드 설명이 주가 될 듯 하다. 

1.2 Strengths and Weaknesses of C

 다른 프로그래밍 언어들처럼, C도 장단점이 있다. 장단점 모두 언어의 초기 사용법과 근본 철학에서 나온다. 다음은 C의 근본 철학이다.

  • C는 low-level언어이다. 시스템 프로그래밍에 최적화하기 위해서, C는 다른 언어들이 숨기려고 하는 기계적 수준의 개념(바이트나 주소값)에 접근하는 것을 제공해야한다. 또한 C는 컴퓨터 내부 부품에 가깝게 소통하는 명령을 제공하여 빠른 속도의 프로그램을 제공해야한다. 애플리케이션 프로그램이 입출력 저장관리에 의존하기 때문에, 수많은 서비스들, OS는 느리게 동작해서는 안된다.

 

  • C는 작은 언어이다. C는 다른 언어들에 비해 제공되는 기능이 제한되어있다. 기능을 줄여, C는 '라이브러리'라는 표준 기능에 크게 의존한다. 

 

  • C는 관대한 언어이다. C는 무엇을 하든 허용해주기에 다른 언어들보다 자유도가 높다. 게다가 C는 다른 언어에서 볼수 있는 디테일한 에러체크를 할 수 있는 권한이 없다.

Strengths

  • 효율성. 효율성은 처음부터 C의 장점중 하나였다. 전통적으로 어셈블리어로 작성해오던 애플리케이션들을 대체했기 때문이다. 이것은 C프로그램이 빠르게 돌아가고, 제한된 양의 메모리를 사용하는 데 중요한 역할을 한다.

 

  • 이식성. C의 첫번째 목표가 프로그램 이식성이 아니긴 했지만, 이 언어의 강점중 하나로 밝혀졌다. 컴퓨터에서 슈퍼컴퓨터까지의 범위에서 작동하는 프로그램은 대부분 C로 쓰여졌다. C프로그램 이식성의 이유중 하나는, UNIX와의 연계와 ANSI/ISO표준 덕분에, 모순되지 않는 야매가 생기지 않았다는 것이다. 또다른 이유는, C 컴파일러가 작고 읽기 쉬워 넓게 사용되게 만드는데 도움을 준 것이다. 결국 C는 이식성이라는 특성을 스스로 가지게 되었다.

 

  • 파워. C의 방대한 데이터 형과 연산자는 이 언어를 강력하게 만들었다. 종종 적은 줄의 코드로도 상당히 많은것을 이뤄낼 수 있게 해주었다.

 

  • 융통성. C가 시스템 프로그래밍을 위해 디자인되기는 했지만, 그 분야에만 제한되지 않았다. C는 이제 모든 종류의 어플리케이션에도 사용된다. 임베디드 시스템부터 상업 데이터 프로세싱, 게다가 C는 다른 언어에서 불가능한 연산이 종종 허용되는 등 기능 사용에 대해 제한이 매우 적다. C를 사용했을 때 문자를 정수값이나 부동 소숫점이 있는 수에 추가할 수 있다. 이러한 융통성은 일부 버그를 통과시킬 수 있지만, 프로그래밍을 쉽게 만들수도 있다.

 

  • 표준 라이브러리. C의 가장 큰 강점중 하나는 입력/출력, 문자열처리, 스토리지 할당 및 기타 유용한 작업에 대해 수백가지 기능을 포함하는 표준 라이브러리이다.

 

  • UNIX 통합 환경. C는 UNIX 혹은 LINUX 와 함께 사용할 때 특히 강력하다. 실제로 일부 UNIX 도구는 사용자가 C를 알고있다고 가정하기도 한다.

 

Weaknesses

  • C프로그램은 오류가 잘 생긴다. C의 융통성은 오히려 오류가 발생하기 쉽다는 단점이 있다. 다른 많은 언어에서 감지해주는 프로그래밍 실수는 C컴파일러에 의해서는 감지되지 않는다. 이런점에서, 대부분의 오류가 프로그램이 실행될 때까지 감지되지 않는 어셈블리언어와 유사하다. 게다가, C는 조심하지 않는다면 걸릴 수 있는 함정이 많다. 뒤에서 다루겠지만, 추가 세미콜론이 무한 루프 또는 &기호를 누락시키는 경우가 있다.

 

  • C프로그램은 이해하기 어려울 수 있다. C는 대부분 작은 언어지만, 다른 프로그래밍 언어들에서 찾을 수 없는 여러 기능을 갖고 있다. 이러한 기능들은 다양하게 결합할 수 있는데, 프로그램의 작성자만 알아보기 쉬운 코드가 나올 수 있다. 또, C프로그램이 간결한 특성도 단점이 될 수 있다. C는 컴퓨터와 상호작용이 힘든 경우에 최적화되어 설계되었다. 그 결과, C는 프로그램 입력 및 편집에 필요한 시간을 최소화하기 위해 의도적으로 간결하게 유지되었다. C의 유연성 또한 단점이 될 수 있는데, 자신이 만들고도 이해하기 어려워하는 프로그래머들이 생긴다.

 

  • C프로그램은 수정이 어려울 수 있다. C로 작성된 대형 프로그램은 유지보수를 염두에 두고 설계되지 않은 경우 변경하기 어려울 수 있다. 현대의 프로그래밍 언어는 일반적으로 큰 프로그램을 보다 관리하기 쉬운 부분으로 나누는 것을 지원하는 클래스나 패키지 같은 기능을 제공하지만, C는 그런 기능들이 없다.

 

Effective Use of C

C를 효과적으로 사용하기 위해서 C의 장점만 활용하고, 단점을 피한다.

  • C pitfalls(함정)을 피하는 방법을 배운다. 이 책에서 함정 표시가 있는데, 그것에 주의하여 읽는다. 

 

  • 소프트웨어 도구를 사용하여 프로그램의 안정성을 높인다. C프로그래머는 툴 빌더/유저이다. LINT라는 이름의 C도구가 있는데, 전통적으로 UNIX와 함꼐 제공되며 대부분의 C 컴파일러보다 더 광범위한 오류 분석을 프로그램에 적용할 수 있다. LINT나 유사 프로그램을 사용할 수 있다면 사용하는 것이 좋다. 또한 디버그라는 유용한 도구도 있다. C의 특성상 C컴파일러에 의해 많은 버그를 잡기 힘들다. 대신 런타임오류 혹은 잘못된 출력으로 나온다. 그래서 좋은 디버거를 사용하는 것이 C프로그래머들에게 사실상 필수이다.

 

  • 기존 코드 라이브러리를 활용한다. 많은 사람들이 C를 사용하기에 가질 수 있는 이점중 하나이다. C코드는 종종 라이브러리(기능을 모아둔 것)이 번들로 제공된다. 적합한 라이브러리를 구하는 것은 오류를 줄이고 프로그래밍 노력을 상당히 절약할 수 있는 좋은 방법이다. 공통 업무, 사용자 인터페이스 개발, 그래픽, 통신, 데이터베이스 관리 및 네트워킹을 포함한 라이브러리를 쉽게 이용할 수 있다. 어떤 라이브러리들은 퍼블릭 도메인에 존재하고, 오픈소스에도 있으며, 유료로 팔기도 한다.

 

  • 합리적인 일련의 코딩 규약을 채택한다. 코딩 규칙은 언어에 의해 시행되지 않더라도 프로그래머가 채택하기로 결정한 스타일 규칙이다. 잘 선택된 규칙은 프로그램을 보다 균일하고 읽기 쉽고 수정하기 쉽게 한다. 규칙은 프로그래밍 언어를 사용할 때 중요하지만, 특히 C를 사용할 때는 더욱 중요하다. 위에서 언급한 바와 같이, C의 유연성이 뛰어나서 프로그래머들은 거의 읽을 수 없는 코드를 작성하기도 한다. 

 

  • '트릭'을 피하고, 과도하게 복잡한 코드는 피해라. C는 트릭을 지원한다. C로 주어진 작업을 수행하는 방법이 여러가지가 있는데, 프로그래머들은 종종 가장 간단하고 간결한 코드를 선택하려고 한다. 그러나, 종종 가장 짧은 해결책은 이해하기 어려운 코드를 낳는다. 

 

  • 표준을 준수한다. 대부분의 C컴파일러는 C89 C99표준의 일부가 아닌 언어기능과 라이브러리 기능을 제공한다. 이식성을 위해서 반드시 필요하지 않은 경우, 비표준 기능, 비표준 라이브러리를 사용하지 않는 것이 가장 좋다.

 

“When someone says: ‘I want a programming language in which I need only say what I wish done’, give him a lollipop.”
'누군가가 원하는 것을 말하기만 하면 되는 프로그래밍 언어를 원한다고 하면, 그에게 사탕을 줘라'
– 앨런 펄리스(Alan J. Perlis)

이 책의 서두부터, C언어가 무엇인지를 한 문장으로 정의해준다. "가장 넓게 쓰이는 프로그래밍 언어로, 1970년 초반(1972년)에 벨 연구소에서 만들어진 언어이다. C에 대한 전반적인 역사, 무엇을 위해 만들어졌고, 시간이 지나며 어떻게 변했는지를 소개한다. 1.1에서는 C의 역사를, 1.2에서는 장단점을 소개한다.

 

1.1 History of C

Origins

  C는 벨 연구소의 Ken Thompson, Dennis Ritchie 등이 개발한 UNIX OS에서 파생되었다. UNIX는 그당시 다른 OS들과 마찬가지로 어셈블리어로 쓰여졌다. 어셈블리어는 유지보수하기 매우 힘들었기에, Thompson은 UNIX의 더 나은 발전을 위해 high-level의 언어가 필요하다고 결심한다. 그렇게 BCPL의 앞글자인 B라는 언어를 만들었다. 이어서 Ritchie가 UNIX 프로젝트에 참여하고 B로 프로그래밍하기 시작했다. 1970년, PDP-11을 UNIX에 적용시키기 위해 Thompson은 UNIX를 B로 일부 수정하였고, 1971년에 B가 UNIX에 적합한 언어가 아님이 명백해졌다.

 그렇게 1972년에 Ritchie가 B의 확장버전을 만들게 된다. 처음에는 새로운 B라는 의미의 NB라고 불렸으나 B와 다른부분이 많이 생기자 C로 바꾸었다. C언어는 1973년, UNIX를 C로 수정하기에 충분히 안정적이었다. C로 바꾸면서 갖게된 중요한 장점은 이식성이다. 다른 컴퓨터에서 작성된 C컴파일러는 UNIX가 돌아가는 다른 기계에서도 잘 작동했다.

Standardization

 C는 1970년대 이후로 계속 발전했지만, 특히 1977년에서 1979년에 K&R이라는 책이 나오면서 크게 발전했다. Brian Kernighan과 Dennis Ritchie가 출판했는데, 정식명칭은 The C Programming Language이고, C프로그래머들의 교과서가 되었다. 이 책은 지금도 사실상 C언어의 공식 표준으로 남아있다. 

 70년도에는, C프로그래머들이 비교적 적었고, 그들 중 대다수는 UNIX유저였다. 그러나 1980년이 되면서 C는 다른 OS를 기반으로하는 다양한 기계들에서도 적합하게 돌아가는것이 밝혀졌다. 특히, 이때 급성장한 IBM컴퓨터 플랫폼에서 발전하기 시작했다.

 C가 유명해지면서 문제도 생겼다. 새로운 C컴파일러를 쓰는 프로그래머들은 K&R에만 의존할 수 밖에 없었다. K&R은 몇몇 언어의 기능이 추상적이었고, 컴파일러들은 종종 이런 기능들을 다르게 대했다. 또한 K&R은 C에 속하는 기능과 UNIX에 속하는 기능에 대한 명확한 구분에 실패했다. 더 심각한 문제는, C가 K&R 출판 이후에도 새로운 기능이 추가되고 오래된 기능이 없어지는 등 계속 발전해갔다는 것이다. 철저하고, 정확하고, 최신의 자료의 필요성이 명백해졌다. 표준 없이, 다양한 야매가 생겨나기 시작했고, C의 이식성이라는 장점을 위협하게 되었다. 

  C의 US표준은 1983년에 ANSI(미국표준기구)의 지원 아래에서 이루어졌다. 많은 수정끝에, 1988년에 표준이 완성되었고, 1989년에 X3.159-1989라는 이름으로 정식 승인이 났다. 1990년에는 ISO(국제 표준화 기구)에서 ISO/IEC 9899:1990이라는 이름으로 국제 표준을 승인받았다. 이런 버전은 주로 C89, C90으로 불리며, 구식버전의 C는 차별화하기 위해 K&R C라고도 부른다. 부록C에 C89와 K&R C에 대해 비교해 두었다. 더 수정을 거쳐서 1999년에 ISO/IEC 9899:1999라는 이름으로 새로운 기준을 갖게 되었고 이를 C99라고 부른다. 

 C99는 아직 전세계적이지 않기 때문에, 몇백만줄의 코드가 옛버전의 C를 쓰기 때문에 C99의 기능이 먹히지 않는 컴파일러도 있다.

C기반 언어

C는 현재 프로그래밍 언어들에도 큰 영향을 미쳤다. 다음은 유명한 C기반 언어들이다.

  • C++ 는 C의 모든 기능들을 포함하지만, 객체지향 프로그래밍을 할 수 있도록 클래스와 다른 기능이 추가되었다.
  • JAVA 는 C++을 기반으로 하여 C기능들을 상속받았다.
  • C# 은 C++과 JAVA에서 파생된 최신 언어이다.
  • Perl 은 원래 꽤 간단한 스크립팅 언어였다. 시간이 지나 성장하면서 C의 기능들을 가지고 왔다.

 새로운 언어들이 나왔는데, C를 배워야할까? 필자는 다음과 같은 이유로 배우는 것이 좋다고 말한다. 첫번째로, C를 배우는 것은 C++과 JAVA 등 C기반언어의 기능에 대해 넓은 통찰력을 기를 수 있게 해준다. 최신언어를 먼저 배운 프로그래머들은 종종 C에서 상속된 기능이나 기본 기능을 숙련하는데 실패하기도 한다. 두번째로, 곳곳에 오래된 C프로그램들이 많다. 어떨때는 이런 코드들을 읽고 유지보수하는 것이 필요하다. 마지막으로 C는 여전히 새로운 소프트웨어를 개발하는데 넓게 쓰이고 있다. 특히 메모리나 CPU의 성능이 제한된 상황이나, C의 단순함이 필요한 상황에서.

 아직 C기반 언어를 써보지 않았다면, 이 책은 그런 언어들을 공부하는데 훌륭한 연습이 될것이다. 이 책에서는 데이터 추상화, 정보은닉, 그리고 객체지향 프로그래밍의 큰 틀을 다루는 원칙을 강조할 것이다. C++은 C의 기능을 모두 갖고 있기에, C++을 다루기 전에 이 책의 모든 것을 배워야한다. 많은 C의 기능들은 C기반 언어에서 찾아볼 수 있다.

 

+ Recent posts