OPEN HYPER STEP
← 목록으로 (화이트햇 보안)
SECURITY · 86 / 96
security
CHAPTER 86 / 96
읽기 약 2
FUNCTION

C 최소 문법: 배열과 문자열


핵심 개념

배열·문자열·strlen/strcpy — C 문자열의 \0 종료. 버퍼 개념 도입.

본문

배열 선언

C📋 코드 (20줄)
#include <stdio.h>

int main(void) {
    // 배열 선언 + 초기화
    int nums[5] = {1, 2, 3, 4, 5};
    char letters[3] = {'A', 'B', 'C'};

    // 인덱스 접근
    printf("%d\n", nums[0]);  // 1
    printf("%d\n", nums[4]);  // 5

    // ⚠️ 범위 외 접근 — 정의되지 않은 동작
    // printf("%d\n", nums[5]);  // 쓰레기 값 또는 크래시

    // 크기
    printf("size: %zu\n", sizeof(nums));  // 20 (4*5)
    printf("len: %zu\n", sizeof(nums) / sizeof(nums[0]));  // 5

    return 0;
}

문자열 — \0 종료가 핵심

C📋 코드 (15줄)
#include <stdio.h>
#include <string.h>

int main(void) {
    // 문자열 = char 배열 + \0 (null 문자)
    char str1[] = "Hello";       // 자동으로 \0 추가 (6바이트)
    char str2[6] = "World";      // 명시적 (W,o,r,l,d,\0)
    char str3[] = {'H','i','\0'}; // 직접 \0 추가

    printf("%s\n", str1);   // Hello
    printf("size: %zu\n", sizeof(str1));  // 6 (Hello + \0)
    printf("len: %zu\n", strlen(str1));   // 5 (\0 제외)

    return 0;
}

strcpy의 위험성

C📋 코드 (12줄)
#include <stdio.h>
#include <string.h>

int main(void) {
    // ❌ 위험: 대상 크기 검사 없음
    char dest[5];
    char src[] = "Hello, World!";  // 13 + \0

    strcpy(dest, src);  // ⚠️ 버퍼 오버플로우
    printf("%s\n", dest);  // 정의되지 않은 동작
    return 0;
}
C📋 코드 (14줄)
// ✅ 안전: strncpy + 명시적 \0
#include <stdio.h>
#include <string.h>

int main(void) {
    char dest[5];
    char src[] = "Hello, World!";

    strncpy(dest, src, sizeof(dest) - 1);
    dest[sizeof(dest) - 1] = '\0';  // 명시적 종료

    printf("%s\n", dest);  // Hell (4 + \0)
    return 0;
}

더 안전한 대안

C📋 코드 (19줄)
// 1. snprintf — 모든 플랫폼
#include <stdio.h>

int main(void) {
    char dest[5];
    snprintf(dest, sizeof(dest), "%s", "Hello, World!");
    // 자동 \0 종료 + 잘림 처리
    printf("%s\n", dest);  // Hell
    return 0;
}


// 2. strlcpy — BSD/macOS (Linux는 libbsd 필요)
// strlcpy(dest, src, sizeof(dest));
// 자동 \0 종료 + 잘림 시 원본 길이 반환


// 3. C11 strcpy_s (Annex K, 선택적 구현)
// errno_t strcpy_s(char *dest, rsize_t destsz, const char *src);

문자열 비교

C📋 코드 (16줄)
#include <stdio.h>
#include <string.h>

int main(void) {
    char a[] = "apple";
    char b[] = "apple";
    char c[] = "banana";

    // ❌ 잘못 — 포인터 주소 비교
    printf("a == b: %d\n", a == b);  // 0 (다른 주소)

    // ✅ 올바름 — 내용 비교
    printf("strcmp(a, b): %d\n", strcmp(a, b));  // 0 (같음)
    printf("strcmp(a, c): %d\n", strcmp(a, c));  // 음수 (a < c)
    return 0;
}

버퍼 = 고정 크기 메모리 영역

C📋 코드 (6줄)
// 버퍼 = 임시 데이터 저장 공간
char input_buffer[256];     // 256바이트 버퍼
char output_buffer[1024];   // 1KB 버퍼

// ⚠️ 버퍼는 고정 크기 — 입력이 더 크면 오버플로우
// 다음 챕터: 포인터로 메모리 직접 다루기

다음 챕터

CH.3 "포인터 기초" — 메모리 주소의 세계 진입.


AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 C 코드의 strcpy/sprintf/gets 같은
위험 함수 사용 위치를 모두 찾고
안전한 대체를 적용해줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

CERT C Coding Standard의 문자열
관련 규칙 Top 10과 위반 사례를
비교 분석해줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 C 프로젝트 전체에서 버퍼 관련
잠재적 취약점을 자동 스캔하고
우선순위 리포트를 만들어줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 OWASP Buffer Overflow 통계와
실제 CVE 발생 빈도를 솔직히 알려줘.

⭐ 이것만 기억하세요
C 최소 문법: 배열과 문자열 이 3가지만 확실히 잡으세요
1.C 문자열은 \0 종료 + char 배열 — strlen은 \0 전까지, sizeof는 전체 바이트
2.strcpy는 대상 크기 검사 없어 위험 — 항상 strncpy/snprintf + 명시적 \0
3.다음 챕터 CH.3에서 포인터 기초 — 메모리 주소를 직접 다루는 핵심


공유하기
진행도 86 / 96