지난 4주간은 고급 언어인 Python 언어로 가변 리스트, 우선순위 큐와 같은 추상화된 데이터 타입을 사용하여 컴퓨터를 다루는 방법을 익혔다. 앞으로의 4주간은 Assembly 언어와 매우 가까운 C를 사용하여 좀 더 컴퓨터의 본질에 가까이 다가가야 한다.
📁 선언(Declaration)과 정의(Definition)
- 선언: 변수나 함수가 어디에 있고, 어떤 타입인지 컴파일러에게 알려주는 것.
- 정의: 실제로 메모리를 할당하거나 함수의 구현부를 작성하는 것.
// header.h
int add(int, int); // 선언
// main.c
#include "header.h"
int add(int a, int b) { return a + b; } // 정의
보통 .h 파일에 선언을, .c 파일에 정의를 한다. 파이썬은 선언 없이 바로 정의하니 이 개념 자체가 생소할 수 있다.
🔁 전방 선언 (Forward Declaration)
C에서는 아래처럼 순서가 중요할 수 있어서, 아직 정의되지 않은 함수나 구조체를 먼저 알려줘야 할 때가 있다.
void hello(); // 전방선언
int main() {
hello();
}
void hello() {
printf("Hi\n");
}
🔒 static과 extern
static: 파일 내 한정 사용 (internal linkage). 외부에서 접근 불가.extern: 다른 파일에 정의된 변수나 함수가 외부에서 사용 가능함을 명시.
// a.c
static int count = 0; // 다른 파일에서는 못 씀
extern int total; // 다른 파일에서 정의된 total 사용
| 키워드 | 의미 | 용도 |
| static | 파일 내부에서만 사용 | 전역 변수나 함수 숨김 |
| extern | 다른 파일에 정의된 변수/함수 사용 | 연결을 위해 선언만 할 때 사용 |
🔘 enum과 union
enum: 상수에 이름 붙이기. 가독성과 유지보수에 좋음.union: 여러 멤버 중 하나만 메모리 차지. 같은 메모리를 여러 타입으로 해석 가능.
enum Color { RED, GREEN, BLUE };
union Data {
int i;
float f;
};
🏗️ 컴파일과 링크
- 컴파일 (compile):
.c→.o(기계어 번역) - 링크 (link): 여러
.o파일 → 실행 파일 (.exe, .out)로 결합
즉, C는 코드를 나눠서 작성하고 나중에 조립해서 실행 파일을 만든다. 파이썬처럼 인터프리터가 직접 실행하는 방식과는 다름.
📌 포인터
void** ptr = 0x00000000FFFF8392;
char* name = (char*) *ptr;
printf("%s", name);
void** ptr2 = 0x00000000FFFF3821;
int64_t* number = (int64_t*) *ptr2;
printf("%p", *number);
- void** ptr: 이중 포인터. 주소를 가리키는 주소.
- *ptr: void* → char* 혹은 int64_t*로 캐스팅 후 역참조
- C는 메모리 주소를 직접 다룰 수 있기 때문에, 복잡한 구조를 효율적으로 처리 가능하지만 디버깅도 어렵다.
📦 malloc과 free
malloc(size): size만큼 메모리 할당. 실패하면 NULL 반환.free(ptr): 할당 해제.
int* arr = malloc(sizeof(int) * 10);
// ... 사용
free(arr);
🔢 배열과 포인터
C의 배열은 사실상 포인터와 유사하게 동작한다.
int arr[3] = {1, 2, 3};
int* p = arr;
printf("%d", *(p + 1)); // 2
🧭 Call by Value vs Call by Reference
- C는 기본적으로 Call by Value (값 복사)
- 참조처럼 쓰려면 포인터를 인자로 넘겨야 한다.
void swap(int* a, int* b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
🔄 가변 인자
#include <stdarg.h>
int sum(int count, ...) {
va_list args;
va_start(args, count);
int total = 0;
for (int i = 0; i < count; ++i)
total += va_arg(args, int);
va_end(args);
return total;
}
stdarg.h사용va_list로 여러 인자 처리va_start,va_arg,va_end순서 지켜야 함
⚙️ 전처리기 명령어
#define: 상수/매크로#include: 다른 파일 포함#ifdef/#ifndef: 조건부 컴파일typedef: 새로운 타입 이름 정의
#define PI 3.14
typedef unsigned int uint;
🔁 리스트 순회 (C++ STL과 유사하게)
Pintos 등에서는 C에서도 리스트 구조체를 정의해 순회 가능하게 구현:
struct list_elem* e;
for (e = list_begin(&mylist); e != list_end(&mylist); e = list_next(e)) {
struct my_struct* s = list_entry(e, struct my_struct, elem);
}
⚡ 비트 연산자
&,|,^,~,<<,>>- 하드웨어 제어나 플래그 처리에 필수
int flags = 0b0101;
flags |= 0b1000; // 특정 비트 ON
🧠 정리
처음에는 C언어의 저수준 특성이 낯설었지만, 메모리와 하드웨어에 가까운 언어인 만큼 운영체제나 시스템 프로그래밍에 강력한 장점이 있다. 이 개념들만 이해해도 Pintos나 커널 공부할 때 훨씬 수월할 듯 하다.
'Krafton Jungle > 3. TIL' 카테고리의 다른 글
| [WEEK06] RB트리의 삽입/삭제에 대해 우리집 강아지 문식이도 알기 쉽게 설명해줘 (0) | 2025.04.19 |
|---|---|
| [WEEK06] 레드-블랙 트리에 대해 우리집 강아지 문식이도 알기 쉽게 설명해줘 (0) | 2025.04.15 |
| [WEEK05] Ubuntu에 C 작업환경 설정하기 (0) | 2025.04.10 |
| [WEEK04] 트리 동형 사상 (0) | 2025.04.09 |
| [WEEK04] 세그먼트 트리 (0) | 2025.04.08 |