[C언어] 포인터, 주소, malloc.. 등등

2025. 8. 8. 00:45·Develop

크래프톤 정글 5~8주차 탐험준비
c는 참 멋있는 언어다. 정글에선 c언어를 f1 레이싱카로 비유한다.

"C언어는 F1 레이스 카와 비슷하다. 그 무엇보다도 빠르고 성능 좋지만, 아무나 운전할 수 없고, 아무나 운전하도록 두어서도 안된다."


지금까지 배워왔던 알고리즘을 C로 구현하는 한주가 되고, malloc, RB-tree, 웹서버 구현등을 해야한다
불편하고 빠르게 달려보자

1. 포인터란?

*를 사용해 해당 주소의 값을 읽는 c언어의 연산자이다.

포인터를 왜 사용하는가에 대해서는
여러가지가 존재하지만 이해하기 쉬운 예를 하나 들자면

c언어에서는 값에 의한 참조와 주소에 의한 참조가 존재한다.

#include <stdio.h>

void increment(int num) {
    num++;
    printf("함수 내 num: %d\n", num);
}

int main() {
    int a = 10;
    increment(a);
    printf("함수 호출 후 a: %d\n", a);
    return 0;
}

이런 경우에 a값은 여전히 10이 나온다.
a의 값을 복사해서 넣어준 것 이기 때문에
함수 안에서는 새로운 값이 만들어지기 때문에 원래있던 a와는 관계가 없기때문에

#include <stdio.h>

void increment(int *num) {
    (*num)++;
    printf("함수 내 num: %d\n", *num);
}

int main() {
    int a = 10;
    increment(&a);
    printf("함수 호출 후 a: %d\n", a);
    return 0;
}

이런 경우에는 주소에 의한 호출이 일어나서 함수안에 있는 num은
기존에 있던 a의 주소를 참조하고 있기 때문에
이때 a의값은 11이 된다.

이렇게 주소를 사용할 때 c언어에서는 * 와 & 연산자를 사용한다.

2. 주소연산자란?

주소 연산자란 변수 앞에 & 키워드를 붙여 메모리주소를 반환하는 연산자이다.

int *ptr = &x; 이런식으로 사용한다면
x의 메모리주소를 ptr에 저장하고, *ptr 을 사용하면 해당 주소의 값을 참조한다.

그럼 이것들은 언제 많이 사용하는가?

  1. scanf 계열 함수
    1. 입력받은 데이터를 저장하려면 해당주소를 함수에게 알려주어야 하기 때문에 &를 필수적으로 사용한다.
  2. 함수에서 값 변경/반환
    1. 이 경우엔 리턴하지 않아도 주소를 참조하고 있는 포인터의 값을 넣어줄 수 있기 때문에 편리하다.
  3. 큰 데이터 효율적 전달
    1. 복사없이 주소로만 연산
  4. 동적 메모리 할당(중요)
    1. 동적으로 메모리를 할당 시 메모리를 지정해줘야 한다
  5. 자료구조 구현

이 외에도 많이 사용하겠지만
여러가지 함수, 기능을 작성하면서 익히는 것이 효율적일 것이라 생각된다.

자료구조, 이중포인터는 감도 안잡힌다..

c 프로그래밍은 값 전달만 지원하기 때문에
포인터를 꼭 사용해야 한다.

3. 동적 메모리 할당이란?

포인터의 연장선으로 동적으로 메모리를 할당하는 malloc 함수가 있다.

이 함수의 기능은 힙 영역에 동적으로 메모리를 할당해
유연하고 효율적으로 메모리를 관리할 수 있다.

스택의 메모리 양은 매우 적고,
힙은 상대적으로 매우 크다.

그렇다면 다 힙에 저장하면 되지 않나?

성능차이가 매우 크게 난다.
스택은 low-level에서 봤을 때 매우 간단한 처리를 한다.
(스택레지스터 변경)

그에 비해 힙은 블록리스트 검색, 크기 검사, 블록 분할, 메타데이터 업데이트, 주소 정렬, 포인터 반환 ..

수십~수백개의 cpu명령어를 내려야 하고, 메타데이터로 메모리양도 증가한다.

그 외 캐시미스 등 여러가지 이유에서 두 자료구조의 속도차이가 크게 난다.

그래서 malloc 어떻게 사용하고, 언제 사용?

상황 스택 힙
간단한 변수 ✅ ❌
작은 배열 (<1KB) ✅ ❌
큰 배열 (>10KB) ❌ ✅
크기 미리 알 수 있음 ✅ ❌
크기 런타임 결정 ❌ ✅
성능이 중요 ✅ ❌
함수 밖으로 전달 ❌ ✅

사용법

int *ptr = (int*)malloc(sizeof(int));
if (ptr != NULL) {  // NULL 체크
    *ptr = 10;
    // ... 사용 ...
    free(ptr);      // 반드시 해제
    ptr = NULL;     // NULL로 설정
}

malloc, free 주의점

메모리를 할당했으면 꼭 해제해줘야 한다.
불필요하게 메모리를 사용하면서 메모리누수가 발생하고,
이는 점차 프로그램이 망가지기 시작한다.

하지만 스택도 막 사용한다면 스택오버플로우가 발생하면서
프로그램은 바로 망가진다.

즉 천천히 말라죽는것이 힙메모리영역
단번에 죽는것이 스택영역이다.

'Develop' 카테고리의 다른 글

malloc lab-implicit list에 관하여 + 구현  (3) 2025.08.23
Red-Black Tree 개념  (3) 2025.08.15
Longest Common Subsequence  (5) 2025.08.04
위상정렬 Topological Sort  (3) 2025.07.29
우선순위 큐  (2) 2025.07.23
'Develop' 카테고리의 다른 글
  • malloc lab-implicit list에 관하여 + 구현
  • Red-Black Tree 개념
  • Longest Common Subsequence
  • 위상정렬 Topological Sort
sj-leeee
sj-leeee
배운것과 느낀것을 적는 공간입니다.
  • sj-leeee
    sj-leeee 님의 블로그
    sj-leeee
  • 전체
    오늘
    어제
    • 분류 전체보기 (23) N
      • LIFE (5)
      • Develop (17) N
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

    • 깃허브
    • 이전블로그
  • 공지사항

  • 인기 글

  • 태그

    malloc
    정글
    heap
    8주차
    Algorithm
    Pintos
    krafton
    rbtree
    MQ
    컴파일
    node.js
    운영체제
    크래프톤정글
    싱글스레드
    LinkedList
    Jungle
    크래프톤
    git
    Kafka
    AWS
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
sj-leeee
[C언어] 포인터, 주소, malloc.. 등등
상단으로

티스토리툴바