
C 언어로 어록을 출력하는 간단한 프로그램을 작성해보자.
#include <stdio.h>
int main(void)
{
printf("To C, or not to C: that is the question.\n");
return 0;
}
#include는 C의 표준 입출력 라이브러리에 대한 정보를 불러온다.printf는 표준 입출력 라이브러리에 내장된 함수로 데이터를 출력한다.C 언어는 컴퓨터가 실행할 수 있는 형태로 만들어지기까지 다음 3단계를 거친다.
프로그램은 우선 전처리기(Preprocessor)로 보내진다. #로 시작하는 지시어(directive)를 읽으며 프로그램에 무언가를 추가하고 수정한다.
프로그램은 이제 컴파일러(Compiler)로 보내진다. 여기서 코드는 기계어(목적 코드, Object code)로 변환된다. 하지만 아직 프로그램을 실행할 수 있는 형태는 아니다.
마지막 단계에선 링커(Linker)가 컴파일된 목적 코드(Object code)를 프로그램을 완벽하게 실행하기 위해 필요한 추가적인 코드와 합친다. 이 추가적인 코드는 보통 프로그램에 사용되는 라이브러리 내부의 명령문을 의미한다. 위 코드를 예시로 들면 printf가 해당된다.
UNIX에서 C 프로그램을 컴파일하려면 다음과 같은 명령문을 사용한다.
% cc pun.c
컴파일과 링킹이 끝나면, cc는 실행 가능한 프로그램을 a.out이라는 이름으로 만들어낸다. -o 옵션을 사용하면 프로그램 이름을 지정할 수 있다.
% cc -o pun pun.c
GCC 컴파일러는 가장 유명한 C 컴파일러 중 하나이며 리눅스에서 기본 제공된다.
간단한 C 프로그램은 다음과 같은 구조를 가진다.
*directives*
int main(void)
{
*statements*
}
이 세 가지 개념에 대해 구체적으로 알아보자.
C는 컴파일 전 전처리 단계를 거친다. 이 전처리에 사용되는 명령문을 지시자라고 한다. 14, 15단원에서 보다 구체적으로 다룬다. 우선 #include 지시자에 대해 알아보자.
#include <stdio.h>
이 줄은 <stdio.h>에 존재하는 정보들을 컴파일 이전에 프로그램에 포함시킨다는 의미이다. <stdio.h>는 C의 표준 입출력 라이브러리에 대한 정보를 담고 있다.
C는 <stdio.h>와 같은 헤더라고 불리는 것이 존재한다. 헤더는 표준 라이브러리의 여러 부분을 포함하고 있다. C는 다른 언어와 달리 기본 내장 함수가 없기 때문에 표준 라이브러리에서 필요한 기능을 받아와 사용해야 한다.
지시자는 언제나 #으로 시작해야 한다. 또한 마지막에 세미콜론(;)과 같은 특수기호를 붙이지 않는다.
C 프로그램을 제작할 때 main 함수가 필수적으로 들어가야 한다. main 함수는 프로그램이 실행될 때 자동으로 실행되는 특별한 함수이다.
main 함수는 프로그램이 종료될 때 운영체제에 상태 코드(status code)를 반환한다. pun.c에서는 0이라는 값을 반환하는데 이는 일반적인 프로그램 종료를 의미한다.
return 구문이 main 함수 마지막에 없더라도 프로그램은 종료된다. 다만 main 함수가 정수값을 반환받지 못했으므로 컴파일러가 에러 메시지를 출력한다.
각 구문은 세미콜론(;)으로 끝나야 한다. 단, 복합문(Compound statement)처럼 세미콜론이 필요 없는 유일한 예외도 있다.
주석은 다음과 같이 작성할 수 있다.
/* 이것은 주석입니다 */
여러 줄 주석은 다음과 같이 작성할 수 있다.
/* 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) /* 메인 프로그램의 시작 */
컴파일러는 /*가 나온 이후 */가 나오지 않는다면 /* 이후에 적힌 모든 문자를 무시한다.
printf("My "); /* 주석 깜빡하고 닫지 않기…
printf("cat ");
printf("has "); /* 여기서 주석이 끝날 것 */
printf("fleas");
따라서 위 코드의 출력 결과는 다음과 같다.
My fleas
[C99] C99를 사용하는 경우 //를 사용해 주석을 달 수 있다.
// 이것은 주석입니다
이 방식으로 여러 줄에 걸쳐 주석 처리를 하고 싶다면 다음과 같이 사용한다.
// Name: pun.c
// Purpose: Prints a bad pun
// Author: K. N. King
이 방식을 사용하면 첫번째 방식처럼 닫지 않는다고 해서 프로그램의 일부가 주석처리 될 일이 없다는 점에서 유용하다.
모든 변수는 반드시 형(type)을 가져야 한다. 당장은 int와 float 두 가지만 다룬다.
변수는 반드시 선언(declare) 되어야 사용할 수 있다.
int height;
float profit;
선언문은 구문 전에 선언해야 한다.
int main(void)
{
*declarations*
*statements*
}
[C99] C99에선 굳이 구문 직전에 오지 않아도 된다. main 함수 내부에서 선언 - 구문 - 또다른 선언 순서로 작성할 수 있다. 다만 구식 컴파일러와 호환성을 위해 위의 방식을 사용하면 좋다.
변수는 할당(assign) 함으로써 값을 가질 수 있다.
height = 8;
length = 12;
width = 10;
선언 후 할당할 수도 있다.
int height;
height = 8;
float형 변수에 할당된 소수점을 갖는 상수에는 끝에 f를 붙인다.
profit = 2150.48f;
printf를 이용해 변수의 값을 출력할 수 있다.
printf("Height: %d\n", height);
%d는 int형 변수만 대신할 수 있다. float형 변수는 %f를 이용해서 대신할 수 있다. %f는 기본적으로 소수점 이하 여섯자리까지 출력한다. %f로 소수점 이하 p 자리까지 출력하려면 %와 f 사이에 .p를 적어주면 된다.
print(Profit: $%.2f\n", profit);
printf가 출력할 수 있는 변수의 개수는 제한이 없다. 다음과 같이 2개를 동시에 출력할 수 있다.
print(Height: %d Length: %d\n", height, length);
변수 선언과 할당을 동시에 함으로써 초기값을 설정할 수 있다.
int height = 8;
초기화되지 않은 변수의 값을 출력하려고 하거나 표현식에서 사용한다면 예상치 못한 결과를 반환하거나 심한 경우 프로그램이 중단될 수 있다.
printf는 모든 표현식을 출력할 수 있다.
printf("%d\n", height * length * width);
입력값을 받으려면 scanf 함수를 사용해야 한다. scanf와 printf의 f는 formatted의 약자이다. 둘 다 데이터를 입력받거나 출력할 때 format string이 필요하다. printf처럼 scanf도 입력받는 데이터 타입을 정해줘야 한다.
int형 변수를 입력받을 때는 다음과 같이 사용한다.
scanf("%d", &i); /* 정수를 받아 i에 저장한다. */
scanf("%d", &i); /* reads an integer; stores into i */
&의 기능은 추후 알아보자.
매크로 정의(macro definition)을 사용해 상수를 선언할 수 있다.
#define INCHES_PER_POUND (166)
매크로의 값은 표현식이 될 수 있다.
#define RECIPROCAL_OF_PI (1.0f / 3.14159f)
Reciprocal은 역수라는 의미이다. 만약 연산자가 표현식에 존재한다면 괄호를 통해 열고 닫아줘야한다.
변수, 함수, 매크로 등에 붙여주는 이름을 식별자(Identifier)라고 부른다. C에서 식별자를 정의할 때 문자, 숫자, _를 사용할 수 있다. 단, 식별자를 숫자로 시작할 수는 없다.
[C99] C99에선 식별자에 특정 유니버설 문자명(Universal character name)을 포함할 수 있다.
다음은 식별자로 가능한 경우들이다.
times10 get_next_char _done
다음은 불가능한 경우들이다.
10times get-next-char
C는 대소문자를 구별한다. 아래는 서로 다른 식별자들이다.
job joB jOb jOB Job JoB JOb JOB
[C99] C 컴파일러에선 아래 표에 명시된 일부 키워드를 식별자로 사용할 수 없다. C99에는 다섯가지가 더 추가되었다.
auto | enum | restrict | unsigned |
|---|---|---|---|
break | hextern | return | void |
case | float | short | volatile |
char | for | signed | while |
const | goto | sizeof | _Bool † |
continue | if | static | _Complex † |
default | inline † | struct | _Imaginary † |
do | int | switch | |
double | enum | typedef | |
less | long | union |
†: C99에서 추가된 키워드