기본
Hello World
#include int main(void) { printf("Hello, World!\n"); return 0; }
컴파일 & 실행
gcc -o app main.c # compile gcc -Wall -Wextra -std=c17 main.c # strict ./app # run
주석
// single-line comment (C99+) /* multi-line comment */
데이터 타입
기본 타입
char1바이트, 문자 또는 소형 정수
short최소 16비트
int최소 16비트 (일반적으로 32)
long최소 32비트
long long최소 64비트 (C99+)
float32비트 IEEE-754
double64비트 IEEE-754
_Bool / bool0 또는 1 (bool 사용)
고정 너비 타입 (stdint.h)
int8_t, uint8_t정확히 8비트 부호 있음/없음
int16_t, uint16_t정확히 16비트
int32_t, uint32_t정확히 32비트
int64_t, uint64_t정확히 64비트
size_t부호 없음, sizeof 결과
타입 캐스팅
int i = (int)3.14; // explicit cast double d = (double)5 / 2; // 2.5, not 2 char c = (char)65; // 'A'
제어 흐름
If / Else
if (x > 0) { printf("positive\n"); } else if (x == 0) { printf("zero\n"); } else { printf("negative\n"); }
Switch
switch (choice) { case 1: printf("one\n"); break; case 2: printf("two\n"); break; default: printf("other\n"); }
반복문
for (int i = 0; i < 10; i++) { } while (condition) { } do { } while (condition);
점프 구문
break가장 안쪽 루프 또는 switch 종료
continue다음 반복으로 건너뜀
return선택적 값과 함께 함수 종료
goto label레이블로 점프 (신중히 사용)
함수
선언 & 정의
int add(int a, int b); // prototype int add(int a, int b) { return a + b; }
함수 포인터
int (*op)(int, int) = add; int result = op(3, 4); // calls add(3, 4) typedef int (*MathFn)(int, int); MathFn fn = add;
정적 함수
// visible only within this translation unit static int helper(int x) { return x * 2; }
포인터
포인터 기본
int x = 42; int *p = &x; // p points to x printf("%d\n", *p); // dereference: 42 *p = 100; // x is now 100
포인터 산술
int arr[] = {10, 20, 30}; int *p = arr; printf("%d\n", *(p + 1)); // 20 printf("%d\n", p[2]); // 30 (same as *(p+2))
일반 포인터 패턴
int *p = NULLnull 포인터 (항상 초기화)
void *범용 포인터 (사용 시 캐스팅 필요)
const int *p상수 포인터 (값 수정 불가)
int *const p상수 포인터 (포인터 재할당 불가)
int **pp포인터의 포인터 (이중 간접)
배열 & 문자열
배열
int nums[5] = {1, 2, 3, 4, 5}; int matrix[2][3] = {{1,2,3}, {4,5,6}}; int len = sizeof(nums) / sizeof(nums[0]);
문자열 함수 (string.h)
strlen(s)길이 (null 종료자 제외)
strcpy(dst, src)문자열 복사 (안전하지 않음, strncpy 권장)
strncpy(dst, src, n)최대 n개 문자 복사
strcat(dst, src)문자열 연결
strcmp(a, b)비교: 같으면 0, 아니면 <0 또는 >0
strchr(s, c)문자의 첫 번째 발생 위치 찾기
strstr(haystack, needle)부분 문자열 찾기
문자열 리터럴
char greeting[] = "hello"; // mutable array const char *msg = "world"; // pointer to literal char buf[64]; snprintf(buf, sizeof(buf), "%s %s", greeting, msg);
구조체
정의 & 사용
struct Point { double x; double y; }; struct Point p = {1.0, 2.0}; printf("(%g, %g)\n", p.x, p.y);
Typedef
typedef struct { char name[50]; int age; } Person; Person p = {"Alice", 30};
구조체 포인터
void set_age(Person *p, int age) { p->age = age; // arrow operator }
열거형 & 공용체
enum Color { RED, GREEN, BLUE }; union Data { int i; float f; char c; }; // union members share the same memory
메모리 관리
동적 할당 (stdlib.h)
int *arr = malloc(10 * sizeof(int)); if (arr == NULL) { /* handle error */ } arr = realloc(arr, 20 * sizeof(int)); free(arr); arr = NULL; // avoid dangling pointer
할당 함수
malloc(size)초기화되지 않은 메모리 할당
calloc(count, size)할당 및 0으로 초기화
realloc(ptr, size)이전에 할당된 블록 크기 조정
free(ptr)할당된 메모리 해제
일반적인 함정
Memory leak할당된 메모리를 free() 하지 않음
Double free같은 포인터를 두 번 free() 호출
Dangling pointerfree() 후 포인터 사용 — NULL로 설정
Buffer overflow할당된 경계를 넘어 쓰기
파일 I/O
파일 읽기
FILE *f = fopen("data.txt", "r"); if (!f) { perror("open"); return 1; } char line[256]; while (fgets(line, sizeof(line), f)) printf("%s", line); fclose(f);
파일 쓰기
FILE *f = fopen("out.txt", "w"); fprintf(f, "value: %d\n", 42); fputs("hello\n", f); fclose(f);
파일 모드
"r"읽기 (파일 존재 필요)
"w"쓰기 (잘라내거나 생성)
"a"추가 (없으면 생성)
"rb", "wb"바이너리 읽기 / 쓰기
"r+"읽기 및 쓰기 (파일 존재 필요)
전처리기
지시어
#include // system header #include "myheader.h" // local header #define PI 3.14159 #define MAX(a, b) ((a) > (b) ? (a) : (b))
조건부 컴파일
#ifdef DEBUG printf("debug: x = %d\n", x); #endif #ifndef HEADER_H /* include guard */ #define HEADER_H /* ... */ #endif
주요 매크로
__FILE__현재 소스 파일명
__LINE__현재 줄 번호
__func__현재 함수 이름 (C99+)
__DATE__컴파일 날짜 문자열
NULLnull 포인터 상수
sizeof(x)타입 또는 변수의 바이트 크기