C언어 - 통합 예제 (프로그래밍 언어의 5가지 문법 요소)

1. 통합 예제

다음의 예제는 C 프로그래밍 언어의 5가지 문법 요소(변수·연산·문장·제어·함수)를 모두 사용하고, C90 표준 기준 예약어 32개전처리 지시자 12개를 하나의 컴파일 가능한 소스 파일에 담은 종합 예제이다.

exam.c
/*
 * exam.c - C 언어 문법 종합 예제
 *
 */

// #include - C 헤더 포함
#include <stdio.h>
#include <stdlib.h>

// #define - 매크로 정의
#define MAX_COUNT       5
#define BUF_SIZE        64
#define DEBUG_LEVEL     0

// #undef - 매크로 정의 해제
#undef  DEBUG_LEVEL
#define DEBUG_LEVEL     1

// #ifndef / #endif - 매크로가 정의되지 않은 경우에만 컴파일
#ifndef RELEASE
#define RELEASE
#endif

// #if / #elif / #else / #endif - 조건부 컴파일
#if   DEBUG_LEVEL == 0
    #define BUILD_TYPE "Release"
#elif DEBUG_LEVEL == 1
    #define BUILD_TYPE "Debug"
#else
    #define BUILD_TYPE "Unknown"
#endif

// #ifdef / #error / #endif - 특정 매크로가 정의된 경우 컴파일 오류 발생
#ifdef DEBUG_MODE
#error "DEBUG_MODE must not be defined in production builds"
#endif

// #line  - 컴파일러 줄 번호를 100으로 재설정
#line 100

// #pragma - 컴파일러 지시문
// 다음 예제는 의도적으로 사용하지 않은 변수 경고를 무시하도록 처리
#pragma GCC diagnostic ignored "-Wunused-variable"

/* ------------------------------------------------------------------ */
/*  Type definitions  (typedef struct enum union)                     */
/* ------------------------------------------------------------------ */

// typedef + struct
typedef struct {
    int x;
    int y;
} Point;

// typedef + union
typedef union {
    int   i;
    float f;
} Number;

// typedef + enum
typedef enum {
    STATUS_IDLE    = 0,
    STATUS_RUNNING = 1,
    STATUS_DONE    = 2
} Status;

/* ------------------------------------------------------------------ */
/*  File-scope storage class keywords                                 */
/* ------------------------------------------------------------------ */

// extern - 다른 .c 파일에 있는 함수를 여기서 사용한다고 알림
extern void external_log(const char *msg);

// static  - 내부 연결; 호출 간 값 유지
static int call_count = 0;

// volatile - 일반 흐름 밖에서 값이 바뀔 수 있음
volatile int interrupt_flag = 0;

/* ------------------------------------------------------------------ */
/* Function prototypes                                                */
/* ------------------------------------------------------------------ */
int    increase(int value);
void   print_info(const char *label, int value);
double compute_average(int *arr, unsigned int size);
void   demonstrate_types(void);

/* main 함수 */
int main(void)
{
    // auto - 자동(지역) 저장 기간
    auto int count = 0;

    // const - 읽기 전용 변수
    const int LIMIT = 3;

    // register - CPU 레지스터 저장 힌트
    register int i;

    // 기본 자료형 키워드
    short         s     = 10;
    long          l     = 100000L;
    unsigned int  u     = 255u;
    signed char   sc    = -1;
    char          grade = 'A';
    float         ratio = 0.75f;
    double        pi    = 3.14159265358979;

    // 복합 타입
    Point  p      = {10, 20};
    Number num;
    Status status = STATUS_IDLE;
    int    arr[MAX_COUNT];

    // static 지역 변수
    static int run_count = 0;

    // #pragma 동작을 보여주기 위한 의도적 미사용 변수
    int unused_var;

    // 연산: 산술, 비교, 논리
    count  = count + 1;          // + (산술)
    count  = count - 1;          // - (산술)
    u      = u / 5;              // / (산술)
    s      = (short)(s * 2);     // * (산술)
    num.i  = (int)pi % 3;        // % (산술)
    run_count++;
    call_count++;

    // sizeof 연산자
    printf("sizeof(int)    = %u bytes\n", (unsigned)sizeof(int));
    printf("sizeof(double) = %u bytes\n", (unsigned)sizeof(double));
    printf("sizeof(Point)  = %u bytes\n", (unsigned)sizeof(Point));

    // control: while
    while (count < MAX_COUNT) {
        if (count == LIMIT) {    // if
            break;               // break
        } else {                 // else
            count = increase(count);
        }
    }

    // control: do-while + continue
    do {
        call_count++;
        if (call_count % 2 == 0) {
            continue;            // continue
        }
        print_info("call_count", call_count);
    } while (call_count < 4);   // while

    // control: for
    for (i = 0; i < MAX_COUNT; i++) {
        arr[i] = i + 1;
    }

    // control: switch / case / default
    switch (status) {
        case STATUS_IDLE:
            status = STATUS_RUNNING;
            break;
        case STATUS_RUNNING:
            status = STATUS_DONE;
            break;
        default:
            break;
    }

    // control: goto
    if (interrupt_flag != 0) {
        /*
            `goto`는 프로그래밍의 흐름 추적을 어렵게 하므로 예외적
             오류 처리 구간을 처리 외에는 가급적 사용하지 않는다.
        */
        goto error_exit;
    }

    // statements: 함수 호출, 입출력
    demonstrate_types();

    print_info("count",  count);
    print_info("LIMIT",  LIMIT);
    print_info("status", (int)status);

    printf("build  = %s\n",      BUILD_TYPE);
    printf("grade  = %c\n",      grade);
    printf("ratio  = %.2f\n",    ratio);
    printf("pi     = %.5f\n",    pi);
    printf("short  = %d\n",      s);
    printf("long   = %ld\n",     l);
    printf("uint   = %u\n",      u);
    printf("schar  = %d\n",      (int)sc);
    printf("point  = (%d, %d)\n", p.x, p.y);
    printf("num.i  = %d\n",      num.i);

    {
        double avg = compute_average(arr, MAX_COUNT);
        printf("avg    = %.1f\n", avg);
    }

    return 0;   /* 반환 */

error_exit:
    fprintf(stderr, "Error: interrupt detected.\n");
    return 1;
}

/* increase - 값을 1 증가시켜 반환 */
int increase(int value)
{
    return value + 1;
}

/* print_info - 문자열 레이블과 정수값 출력 */
void print_info(const char *label, int value)
{
    printf("%-6.6s = %d\n", label, value);
}

/* compute_average - int 배열의 산술 평균 계산 */
double compute_average(int *arr, unsigned int size)
{
    int sum = 0;
    unsigned int j;

    for (j = 0; j < size; j++) {
        sum += arr[j];
    }
    return (double)sum / size;
}

/* demonstrate_types - C90 기본 자료형 사용 예시 */
void demonstrate_types(void)
{
    signed   int   si =  -10;
    unsigned int   ui =   10;
    short    int   sh =    5;
    long     int   li = 1000L;
    char           c  =  'Z';
    float          f  =  1.5f;
    double         d  =  2.5;

    printf("[types] si=%d ui=%u sh=%d li=%ld c=%c f=%.1f d=%.1f\n",
           si, ui, sh, li, c, f, d);
}
exam_func.c
/*
 * exam.c에서 extern으로 선언한 함수 구현 파일
 */

#include <stdio.h>

/* extern 함수 예시 */
void external_log(const char *msg)
{
    printf("[log] %s\n", msg);
}
  • 포함 범위: 변수, 연산, 문장, 제어문, 함수
  • 구성 요소: C90 키워드, 전처리 지시자, 구조체/공용체/열거형, 함수 호출 흐름

1.1. 실행 결과

$ gcc -Wall -std=c11 -o exam exam.c exam_func.c
$ ./exam
sizeof(int)    = 4 bytes
sizeof(double) = 8 bytes
sizeof(Point)  = 8 bytes
call_c = 3
[types] si=-10 ui=10 sh=5 li=1000 c=Z f=1.5 d=2.5
count  = 3
LIMIT  = 3
status = 1
build  = Debug
grade  = A
ratio  = 0.75
pi     = 3.14159
short  = 20
long   = 100000
uint   = 51
schar  = -1
point  = (10, 20)
num.i  = 0
avg    = 3.0

1.2. 제어 흐름

main() starts
  │
  ├─ while (count < MAX_COUNT)
  │    ├─ if (count == LIMIT)  → break  ← exits loop when count becomes 3
  │    └─ else                 → count = increase(count)
  │
  ├─ do-while (call_count < 4)
  │    ├─ if (call_count % 2 == 0) → continue  ← skips output on even values
  │    └─ print_info(...)
  │
  ├─ for (i = 0; i < MAX_COUNT; i++)
  │    └─ arr[i] = i + 1       ← initializes to {1, 2, 3, 4, 5}
  │
  ├─ switch (status)
  │    ├─ STATUS_IDLE    → STATUS_RUNNING
  │    ├─ STATUS_RUNNING → STATUS_DONE
  │    └─ default        → break
  │
  ├─ if (interrupt_flag != 0) → goto error_exit
  │
  ├─ output statements
  │
  └─ return 0

error_exit:
  └─ fprintf(stderr, ...) → return 1