Core Programming/C Standard Library: Resource & Performan

C언어 time.h 시간 처리 함수 완벽 가이드 (time, clock, difftime, mktime)

임베디드 친구 2025. 2. 22. 09:17
반응형

C언어로 프로그램을 개발하다 보면 현재 시간을 화면에 표시하거나, 특정 알고리즘이 실행되는 데 걸리는 시간을 측정해야 하는 상황을 자주 마주하게 됩니다. 로그 시스템 구축, 파일 생성 시간 기록, 혹은 프로그램 성능 최적화 등 시간을 제어하는 기술은 백엔드와 시스템 프로그래밍의 기본입니다. 오늘은 C 표준 라이브러리인 time.h에서 가장 핵심이 되는 함수 4가지를 명확하게 정리하고 실무에서 바로 쓸 수 있는 팁을 공유해 드리겠습니다.

Generated by Gemini AI.

핵심 요약 3줄

  • time.h 라이브러리의 핵심은 1970년 이후 경과 초를 나타내는 time_t 타입과 연/월/일/시/분/초로 분리된 struct tm 구조체입니다.
  • 실제 세상의 흐름은 time()과 difftime()으로 계산하고, 프로그램의 내부 CPU 점유 시간은 clock()을 통해 정밀하게 측정합니다.
  • struct tm을 time_t로 변환하는 mktime() 함수를 사용할 때는 연도에 1900을 빼고, 월에 1을 빼야 하는 독특한 규칙을 주의해야 합니다.

1. time.h 핵심 개념: 데이터 타입 이해하기

C언어에서 시간을 다루기 전에 반드시 알아야 할 두 가지 데이터 타입이 있습니다. 데이터를 정수 형태로 통째로 관리하는 방식과 사람이 읽기 편하게 쪼개서 관리하는 방식입니다.

핵심 데이터 타입 비교

데이터 타입 데이터 형태 특징 및 주요 용도
time_t 정수형 (정수 혹은 실수 형태) Epoch Time(1970년 1월 1일 00:00:00 이후 경과된 초) 기준이며, 시간 계산과 비교에 유리합니다.
struct tm 구조체 (Structure) 연, 월, 일, 시, 분, 초, 요일 등을 독립된 멤버 변수로 나누어 저장하여 화면 출력에 유리합니다.

2. 현재 시간 가져오기: time()

가장 기본이 되는 함수로, 시스템의 현재 유닉스 타임(초 단위)을 가져옵니다.

함수 원형 및 명세

함수명 매개변수 반환 타입 기능
time time_t *tloc (시간을 저장할 변수의 주소 혹은 NULL) time_t 현재 시스템의 Epoch 타임을 반환합니다.

현재 시간 출력 예제 코드

C
 
#include <stdio.h>
#include <time.h>

int main() {
    // 현재 시간을 초 단위로 가져와 정수형 변수에 저장합니다.
    time_t now = time(NULL); 
    
    printf("현재 유닉스 타임: %ld\n", (long)now);
    return 0;
}

3. 프로그램 실행 시간 측정: clock()

clock()은 실제 흐른 벽시계 시각이 아니라, 프로그램(프로세스)이 CPU를 실제로 점유하여 사용한 시간을 측정합니다. 알고리즘의 연산 효율성이나 성능 테스트를 할 때 주로 활용됩니다.

함수 관련 주요 상수

상수 및 함수명 반환 단위 초 단위 변환 방법 용도
clock() 클록 틱 (Clock Ticks) clock() / CLOCKS_PER_SEC 프로세스가 소모한 내부 CPU 타임 측정
CLOCKS_PER_SEC 초당 클록 틱 수 시스템 환경에 따른 초당 틱 카운트 상수 클록 틱을 초 단위 실수로 변환할 때 분모로 사용

CPU 실행 시간 측정 예제 코드

C
 
#include <stdio.h>
#include <time.h>

int main() {
    clock_t start = clock();

    // 성능을 측정할 로직이 들어가는 구간입니다.
    for (volatile long i = 0; i < 100000000; i++); 

    clock_t end = clock();
    
    // 두 클록 틱의 차이를 초당 클록 틱 상수로 나누어 실수형 초 단위로 변환합니다.
    double duration = (double)(end - start) / CLOCKS_PER_SEC;
    printf("CPU 소요 시간: %f초\n", duration);
    
    return 0;
}

4. 두 시간의 차이 계산: difftime()

서로 다른 두 time_t 시점의 간격이 몇 초인지를 계산하여 double 타입으로 반환하는 함수입니다.

함수 원형 및 명세

함수명 매개변수 반환 타입 공식 및 특징
difftime time_t time1, time_t time2 double time1 - time2 결과를 초 단위 실수로 반환하며 연산 오버플로우를 방지합니다.

일반 정수처럼 - 연산자로 뺄 수도 있지만 운영체제나 시스템 환경에 따라 time_t가 내부적으로 구현된 방식(32비트 정수, 64비트 정수 등)이 다를 수 있기 때문에 표준 함수인 difftime()을 사용하는 것이 이식성 측면에서 안전합니다.


5. 시간 구조체 변환: mktime()

사람이 직관적으로 이해할 수 있는 struct tm 형식의 날짜와 시간 데이터를 컴퓨터가 연산하기 좋은 time_t형식으로 변환해 줍니다. 특정 과거 날짜나 미래 날짜를 지정하여 디데이 계산 등을 할 때 필수적으로 사용됩니다.

struct tm 주요 멤버 변수 설정 규칙

멤버 변수 의미 설정 범위 실무 적용 규칙
tm_year 연도 1900년 이후 경과 연도 원하는 연도 - 1900 (예: 2026년은 126 설정)
tm_mon 0 ~ 11 원하는 월 - 1 (예: 5월은 4 설정)
tm_mday 1 ~ 31 달력상의 일자 그대로 입력

날짜 지정 및 유닉스 타임 변환 예제 코드

C
 
#include <stdio.h>
#include <time.h>

int main() {
    struct tm t = {0}; // 구조체 멤버를 모두 0으로 초기화합니다.
    
    t.tm_year = 2026 - 1900; // 2026년을 표현하기 위해 1900을 뺍니다.
    t.tm_mon = 5 - 1;        // 5월을 표현하기 위해 1을 뺍니다.
    t.tm_mday = 5;           // 5일 설정

    // struct tm을 time_t 데이터로 변환합니다.
    time_t result = mktime(&t);
    printf("2026년 5월 5일의 유닉스 타임: %ld\n", (long)result);
    
    return 0;
}

6. 개발을 위한 팁

  • 목적에 맞는 시간 함수 선택: 실무에서 코드를 작성할 때 파일 생성 시간이나 사용자 로그 기록처럼 현실 세계의 시각이 필요하다면 time() 함수를 써야 합니다. 반면 정밀한 알고리즘 성능 비교나 루프 실행 속도를 측정할 때는 시스템의 대기 시간(I/O 웨이트 등)을 배제하고 순수 연산 속도만 잡을 수 있는 clock() 함수를 쓰는 것이 맞습니다.
  • 출력 형식을 위한 연계 활용: time() 함수로 가져온 time_t 데이터는 그 자체로는 숫자에 불과해서 보기 어렵습니다. 이를 문자열로 바로 바꾸려면 ctime() 함수를 쓰거나, localtime() 함수를 통해 struct tm으로 쪼갠 뒤 strftime() 함수를 사용하면 원하는 포맷(예: YYYY-MM-DD HH:MM:SS)으로 깔끔하게 출력할 수 있습니다.

7. 흔히 하는 실수

  • struct tm 구조체의 오프셋 누락: 가장 빈번하게 발생하는 실수가 struct tm 구조체 멤버 변수에 날짜를 곧바로 대입하는 것입니다. t.tm_year = 2026;이라고 쓰면 컴파일러는 이를 3926년으로 인식하게 됩니다. 기준점인 1900을 빼는 연산과 0부터 시작하는 월(tm_mon)에 1을 빼는 규칙을 절대 잊지 마시기 바랍니다.
  • clock() 함수의 오버플로우 문제: clock() 함수가 반환하는 clock_t 타입은 시스템에 따라 표현할 수 있는 한계가 있습니다. 아주 장시간 실행되는 프로세스의 경우 클록 틱 값이 버퍼 크기를 넘어가서 마이너스 값으로 뒤집히는 오버플로우 현상이 발생할 수 있습니다. 수 시간 이상 걸리는 작업의 총 경과 시간을 잴 때는 clock()보다는 time()이나 운영체제 전용 정밀 타이머 API를 활용하는 편이 안전합니다.

맺음말

C언어에서 표준 라이브러리를 사용해 시스템 시간을 제어하고 측정하는 핵심 기법들을 정리해 보았습니다. 요약하자면 현재 시스템 시간을 확보할 때는 time(), 프로세스의 성능 테스트에는 clock(), 시점 간의 간격 계산은 difftime(), 날짜 데이터를 변환할 때는 mktime()을 사용합니다. 각 함수가 요구하는 데이터 타입의 특징과 데이터 입력 시의 오프셋 규칙을 명확히 파악하고 사용하신다면 시간 관련 로직에서 발생하는 버그를 크게 줄일 수 있을 것입니다.

반응형