Krafton Jungle/1. 정글 개발일지

C언어 특강 정리

munsik22 2025. 4. 16. 16:34

(1) 알고리즘

하노이 탑 (재귀)

# 하노이
def hanoi(n):
    if n == 0: return 0
    return hanoi(n-1) * 2 + 1

이진 트리 노드 개수 세기

struct {
    struct node* left;
    struct node* right;
} node;

int count_node(struct node* root) {
    if (root == NULL) return 0;
    int cnt = 1;
    cnt += count_node(root->left);
    cnt += count_node(root->right);
    return cnt;
}

🔹 재귀 사용법: 점화식 + base case 파악 필요


(2) 포인터

포인터 개념

#include <stdio.h>
int main() {
    cha* p; // 자료형
    int a;

    &a; // 참조 연산자
    *p; // 역참조 연산자

    printf("%d\n", sizeof(p)); // 64bit 시스템에서는 8 출력
    return 0;
}
  • 32bit 시스템: 4byte로 2³² byte 표현
  • 64bit 시스템: 8byte로 2⁶⁴ byte 표현 → 가상 메모리 사용
  • Endianness
    • Big Endian: 네트워크 전송 방식
    • Little Endian: 대부분 하드웨어의 저장 방식

Call by value vs Call by reference

int func(int a) {
    a++;
    return a;
}

int main() {
    int a = 0;
    printf("%d\n", func(a)); // 1
    printf("%d\n", a);       // 0
}

🔹 값 복사로 함수 전달 → 원래 변수는 변경되지 않음

int func(int *a) {
    (*a)++;
    return *a;
}

int main() {
    int a = 0;
    printf("%d\n", func(&a)); // 1
    printf("%d\n", a);        // 1
}

🔹 포인터를 통해 메모리 직접 접근 가능

Operator Overloading (C vs Python)

int *a = 0;
int b = 0;
char** c = 0;
++a; // 4 증가
++b;
++c; // 8 증가
printf("%d %d %d\n", a, b, c); // 4 1 8
a = "abc"
b = "def"
print(a+b) # abcdef

c = 1
d = 2
print(c+d) # 3

배열

int A[] = {0, 1, 2};
printf("%p\n", A);       // 배열 시작 주소
printf("%p\n", A + 1);   // +4 차이 (int)
printf("%d\n", *(A + 1)); // 1

int B[][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
printf("%p %p \n", B, B+1);           // {0,1,2}, {3,4,5}의 주소
printf("%p %p \n", *B, *(B+1));       // 0, 3의 주소
printf("%d\n", *(*(B + 2) + 1));      // 7

Memory Layout: Stack vs Heap

[출처] https://medium.com/huawei-developers/stack-vs-heap-understanding-memory-allocation-in-programming-a83a54901416

  • Stack: 함수 호출 시 메모리 쌓임
  • Heap: malloc 사용 시 동적 메모리
  • Static: 데이터 세그먼트
  • Stack Overflow: (무한 재귀 호출 시) 스택이 힙 영역을 침범하여 발생

Character Pointer

char* a = "abc";
printf("%p %p\n", a, &a); // 문자열 주소와 포인터 변수의 주소
printf("%s\n", a);        // abc 출력

🔹 문자열은 initialized data segment에 저장 → 메모리 주소가 낮음

이중 / 삼중 포인터

int** a = (int**)0x1;
int* b = (int*)0x1;
printf("%d %d\n", sizeof(*a), sizeof(*b)); // 8 4
  • 이중 포인터: 포인터가 가리키는 값을 바꿀 때 사용
  • 삼중 포인터: 실제로 많이 쓰이진 않지만, 개념 이해는 필요