C언어 포인터 개념정리_2

2025. 6. 16. 23:52·C/Concept

 

 

 

 

 

 

 

 

 

 

 

 

 

🌟 구조1, & 주소 연산자

더보기

포인터는 메모리 주소를 저장하는 변수로, C언어에서 가장 중요하면서도 어려운 개념 중 하나.

 

① (&) 연산자 개념

  • 정식 명칭: Address-of 연산자 (주소 추출 연산자)
  • 변수가 저장된 메모리의 주소를 반환
  • 사용 방법: &변수명

 

② 메모리 주소란?

  • 컴퓨터의 메모리는 수많은 작은 저장공간들이 일렬로 배열된 구조이다. 각 저장공간마다 고유의 번호가 있는데, 이를 메모리 주소라 부른다. 마치 아파트의 각 호수처럼 각 메모리 공간을 구분하는 번호다.

 

③ 코드 상세 분석

#include <stdio.h>

void main()
{
    int iNum = 90;  // 정수형 변수 iNum을 선언하고 90으로 초기화
    
    // %d: 정수를 10진수로 출력하는 형식 지정자
    // iNum: 변수의 값 (90)을 출력
    printf("iNum 주소: %d\n", iNum);
    
    // &iNum: iNum 변수가 저장된 메모리 주소를 출력
    printf("iNum 주소값: %d\n", &iNum);
}

 

 ㉮ 변수 선언: int iNum = 90;

  • 메모리에 4바이트 공간을 할당받는다.
  • 그 공간에 90이라는 값을 저장한다,
  • 그 공간에는 고유한 주소가 부여된다.

 ㉯ printf

  • 첫 번째 printf로 90이라는 값을 가져온다.
  • 두 번째 printf로 iNum변수의 메모리 주소를 가져온다.

 

④ 메모리 다이어그램 해석

  ㉮ 메모리 구조 분석

  • 주소 영역: 0x001FF2 등의 16진수 주소값들
  • 메모리 내용: 각 메모리 위치에 저장된 값들 (0,1 등)
  • 변수 위치: iNum = 90이 특정 메모리 주소에 저장됨.

  ㉯ 16진수 주소 표기법

  • 0x: 16진수임을 나타내는 접두사
  • 001FF2:  실제 메모리 주소
  • 16진수를 사용하는 이유: 메모리 주소는 보통 매우 큰 숫자이므로 16진수로 표현하면 더 간결하기 때문에

 

⑤ 포인터 학습의 중요성

  ㉮ 왜 포인터를 배워야 하는가?

  • 메모리 직접 제어: 효율적인 메모리 사용 가능
  • 함수 간 데이터 전달: 큰 데이터를 복사하지 않고 주소만 전달
  • 동적 데이터 할당: 프로그램 실행 중 필요한 만큼 메모리 할당

 

 

 

🌟 구조2, * 참조 연산자

더보기

앞서 & 연산자가 주소를 얻는 역할이었다면, * 연산자는 그 주소에 저장된 값에 접근하는 역할

 

① 애스터 리스크 연산자의 두 가지 역할

  ㉮ 포인터 변수 선언

int* p_iNum;  // 정수형 포인터 변수 선언
  • 의미: 정수를 가르키는 포인터 변수를 선언
  • 저장 내용: 메모리 주소값
  • 크기: 포인터는 항상 8바이트 또는 4바이트

㉯ 간접 참조

*p_iNum  // 포인터가 가리키는 위치의 값에 접근
  • 의미: 포인터가 가르키는 메모리 위치에 저장된 실제 값
  • 용도: 포인터를 통해 원본 데이터에 접근하거나 수정

 

② 코드 상쇄 분석

#include <stdio.h>

int main(void)
{
    int iNum = 90;  // 일반 정수 변수 선언 및 초기화
    
    // 변수의 값과 주소 출력
    printf("iNum 변수의 정수값: %d\n", iNum);     // 90 출력
    printf("iNum 변수의 주소값: %p\n", &iNum);    // 메모리 주소 출력
    
    // 포인터 변수 선언 및 초기화
    int* p_iNum = &iNum;  // iNum의 주소를 포인터에 저장
    
    // 포인터를 통한 값 접근
    printf("p_iNum 포인터 변수 값: %p\n", p_iNum);   // 저장된 주소 출력
    printf("p_iNum 포인터 역참조 값: %d\n", *p_iNum); // 가리키는 곳의 값(90) 출력
    
    return 0;
}

  ㉮ 일반 변수 선언

  • 메모리 할당: 4바이트 공간 할당
  • 값 저장: 90이라는 정수값 저장
  • 주소: 시스템이 자동으로 메모리 주소 할당 (예: 0x0061FF17)

  ㉯ 포인터 변수선언

  • 포인터 선언: int* 는 정수를 가르키는 포인터를 의미
  • 초기화: &iNum으로 iNum의 주소를 포인터에 저장
  • 명명 규칙: p_는 포인터임을 나타내는 일반적인 접두사

  ㉰ 출력문 분석

  • p_iNum: 포인터 자체의 값 (저장하고 있는 주소값)
  • 출력 결과: 0x0061FF17 (iNum의 주소)
  • *p_iNum: 포인터가 가리키는 위치의 실제 값
  • 출력 결과: 90 (iNum에 저장된 값)

 

③ 메모리 다이어그램 해석

  ㉮ iNum 변수의 메모리 위치

  • 주소: 0x0061FF17
  • 저장값: 90 (10진수)
  • 바이너리 표현: 이진법으로 변환된 90의 값이 메모리에 저장

  ㉯ p_iNum 포인터의 메모리 위치

  • 주소: 0x0061FF28 (포인터 자체의 주소)
  • 저장값: 0x0061FF17 (iNum의 주소를 저장)
  • 크기: 포인터는 주소를 저장하므로 시스템에 따라 4바이트 또는 8바이트
// 메모리 관계도

[일반 변수]                    [포인터 변수]
주소: 0x0061FF17              주소: 0x0061FF28
┌─────────────┐              ┌─────────────────┐
│    iNum     │              │    p_iNum       │
│     90      │ ◄─────────── │  0x0061FF17     │
└─────────────┘              └─────────────────┘
     값                           주소값

 

④ 핵심 원리

  • 주소 저장: 포인터는 다른 변수의 메모리 주소를 저장하는 변수
  • 간접 접근: * 연산자로 포인터가 가리키는 실제 값에 접근
  • 메모리 효율성: 큰 데이터를 복사하지 않고 주소만 전달하여 효율성 증대

 

 

 

🌟 구조3, 지역변수와 포인터 전달 방식

더보기
int func1(int num)  // 매개변수: 일반 정수형 변수
{
    num = 20;       // 지역변수 num에 20을 대입
    return 0;       // 함수 종료
}

int func2(int* num)  // 매개변수: 정수형 포인터
{
    *num = 20;       // 포인터가 가리키는 위치의 값을 20으로 변경
    return 0;        // 함수 종료
}

int main(void)
{
    int num = 0;  // num 변수를 0으로 초기화
    
    func1(num);                    // 값 전달
    printf("%d", num);             // 결과: 0 출력
    
    func2(&num);                   // 주소 전달
    printf("%d", num);             // 결과: 20 출력
    
    return 0;
}

 

① 함수별 상세 분석

 ㉮ func1 함수 - 값에 의한 전달 (Call by Value)

  ⓐ 동작 원리

  • 매개변수 복사: main 함수의 num 값(0)이 func1의 지역변수 num에 복사
  • 독립적인 메모리: func1의 num은 main의 num과 완전히 별개인 메모리 공간을 사용
  • 값 변경: func1 내에서 num = 20으로 변경해도 main의 num에는 영향 없음
  • 함수 종료: func1이 끝나면 지역변수는 메모리에서 제거됨
// 메모리 구조

[main 함수의 num]          [func1 함수의 num]
주소: 0x1000              주소: 0x2000
┌─────────────┐          ┌─────────────┐
│     0       │          │     20      │ ← 여기서만 변경됨
└─────────────┘          └─────────────┘
   원본 (변경안됨)           복사본 (변경됨)

 

 ㉯ func2 함수 - 참조에 의한 전달 (Call by Reference)

  ⓐ 동작 원리

  • 주소 전달: main 함수의 num 변수의 주소가 func2로 전달
  • 같은 메모리 참조: func2의 포인터는 main의 num과 동일한 메모리 위치를 가리킴
  • 원본 변경: *num = 20으로 원본 데이터를 직접 수정
  • 영구적 변경: 함수가 끝나도 main의 num 값은 변경된 상태로 유지
// 메모리 구조

[main 함수의 num]          [func2 함수의 포인터]
주소: 0x1000              주소: 0x3000
┌─────────────┐          ┌─────────────┐
│     20      │ ◄─────── │  0x1000     │
└─────────────┘          └─────────────┘
   원본 (변경됨)            주소값 저장

 

 

② main 함수 실행 과정 분석

// 초기 상태

int num = 0;  // num 변수를 0으로 초기화

// 첫 번째 함수 호출

func1(num);                    // 값 전달
printf("%d", num);             // 결과: 0 출력

 

㉮ 실행 과정

  • func2(&num) 호출 시 num의 주소가 전달
  • func2 내부에서 포인터를 통해 원본 값을 20으로 변경
  • 함수 종료 후에도 main의 num은 20으로 변경된 상태
  • printf로 20이 출력됨

 

③ 실행 결과 예상

  • 첫 번째 출력 (0): func1은 복사본만 변경했으므로 원본은 그대로
  • 두 번째 출력 (20): func2는 원본을 직접 변경했으므로 값이 바뀜

 

④ 핵심 개념 비교표

구분 값에 의한 전달 (Call by Value) 참조에 의한 전달 (Call by Reference)
매개변수 타입 int num int* num
전달 내용 변수의 값 변수의 주소
매모리 사용 새로운 메모리 할당 기존 메모리 공간 공유
원본 변경 불가능 가능
함수 호출 func(variable) func(&variable)
값 접근/변경 직접 접근 num = 20 간접 접근 *num = 20
메모리 효율성 낮음 (복사 필요) 높음 (주소만 전)

⑤ 지역변수의 특성

정의: 함수 내부에서 선언된 변수

생명주기: 함수가 시작될 때 생성, 함수가 끝날 때 소멸

유효범위: 선언된 함수 내부에서만 접근 가능

//지역변수의 메모리 할당

int func1(int num)  // num은 func1의 지역변수
{
    num = 20;       // 이 num은 main의 num과 다른 변수
    return 0;
}  // 여기서 지역변수 num은 메모리에서 제거됨

 

⑥ 함수 설계 시 고려사항

 ㉮ 값 전달을 선택해야 하는 경우

  • 원본 보호: 함수 내에서 실수로 원본을 변경하는 것을 방지
  • 단순 계산: 입력값을 이용한 계산 결과만 필요한 경우
  • 안전성: 데이터 무결성이 중요한 경우

 ㉯ 포인터 전달을 선택해야 하는 경우

  • 원본 수정: 함수에서 원본 데이터를 변경해야 하는 경우
  • 메모리 효율성: 큰 구조체나 배열을 전달할 때
  • 다중 반환값: 함수에서 여러 값을 반환해야 하는 경우
  • 동적 메모리: malloc으로 할당한 메모리를 다룰 때

 

⑦ 주의사항 및 일반적인 실수

int func(int* num) {
    if (num == NULL) {  // NULL 포인터 체크 필수
        return -1;      // 오류 처리
    }
    *num = 20;
    return 0;
}
  • NULL 포인터 역참조: 포인터가 NULL인지 확인하지 않고 사용
  • 타입 불일치: 포인터 타입과 실제 데이터 타입이 맞지 않는 경우
  • 지역변수 주소 반환: 함수 내 지역변수의 주소를 반환하는 실수

 

 

 

 

 

 

 

 

 

 

 

 

 

 

미리보기용

'C > Concept' 카테고리의 다른 글

C언어 형변환 개념정리  (0) 2025.06.17
C언어 포인터 개념정리_1  (3) 2025.06.13
C언어 소스코드 개념정리  (2) 2025.06.11
'C/Concept' 카테고리의 다른 글
  • C언어 형변환 개념정리
  • C언어 포인터 개념정리_1
  • C언어 소스코드 개념정리
eull
eull
eull 님의 블로그 입니다.
  • eull
    eull 님의 블로그
    eull
  • 전체
    오늘
    어제
    • 개발 환경 (31)
      • MYSQL_Workbench (1)
        • setting (1)
      • Linux_Ubuntu (2)
        • Task (1)
        • Setting (1)
      • C (19)
        • Concept (4)
        • Task (8)
        • Project (1)
        • Study (5)
        • Setting (1)
      • C++ (1)
        • Study (0)
        • Concept (1)
      • Python (6)
        • Task (4)
        • Project (2)
      • 일상 (1)
      • Setting (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
eull
C언어 포인터 개념정리_2
상단으로

티스토리툴바