Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C 언어 근거리(Near), 원거리(Far), 거대(Huge) 포인터 완벽 정리

C 언어에서 포인터는 메모리 모델과 세그먼트 방식에 따라 크게 세 가지 유형으로 분류됩니다.

  • 근거리 포인터(Near Pointer)
  • 원거리 포인터(Far Pointer)
  • 거대 포인터(Huge Pointer)

근거리 포인터(Near Pointer)

  • 메모리의 64KB 데이터 세그먼트 범위 안에서만 동작하는 포인터입니다.
  • 해당 데이터 세그먼트를 벗어난 주소에는 접근할 수 없습니다.
  • 산술 연산자를 이용해 주소 값을 증가시키거나 감소시킬 수 있습니다.
  • near 키워드를 붙이면 어떤 포인터든 근거리 포인터로 만들 수 있습니다.

문법

기본 문법은 다음과 같습니다.

<데이터 타입> near <포인터 정의>
<데이터 타입> near <함수 정의>

아래 문장은 변수 s를 가리키는 근거리 포인터를 선언한 것입니다.

char near *string;

예제 프로그램

다음 예제는 근거리 포인터의 사용법을 보여줍니다.

#include <stdio.h>
int main(){
    int number = 50;
    int near *p;
    p = &number;
    printf("%d", sizeof(p));
    return 0;
}

실행 결과

2

출력 결과가 2바이트인 이유는 근거리 포인터가 세그먼트 내부의 오프셋(offset) 주소만 저장하기 때문입니다. 16비트 환경에서 오프셋은 2바이트로 표현됩니다.

원거리 포인터(Far Pointer)

  • 포인터가 가리키는 대상의 세그먼트(segment) 주소와 오프셋(offset) 주소를 모두 저장합니다.
  • 전체 16개 세그먼트에 접근할 수 있습니다.
  • 주소 표현 범위는 0부터 1MB까지입니다.
  • 포인터를 증가 또는 감소시키면 오프셋 부분만 변경됩니다.

문법

<데이터 타입> far <포인터 정의>
<데이터 타입> far <함수 정의>

아래 문장은 변수 s를 가리키는 원거리 포인터를 선언한 것입니다.

char far *s;

예제 프로그램

#include <stdio.h>
int main(){
    int number = 50;
    int far *p;
    p = &number;
    printf("%d", sizeof(p));
    return 0;
}

실행 결과

4

출력 결과가 4바이트인 이유는 원거리 포인터가 세그먼트 주소(2바이트)와 오프셋 주소(2바이트)를 함께 저장하기 때문입니다.

거대 포인터(Huge Pointer)

  • 크기 면에서 원거리 포인터와 동일하게 32비트 주소를 사용합니다.
  • 세그먼트 경계 넘어감(wrap-around) 문제 없이 증감 연산이 가능합니다.

거대 포인터는 증감 연산 시 세그먼트 값까지 자동으로 조정해 주므로 1MB 전체 메모리를 연속적으로 순회할 수 있습니다. 반면 원거리 포인터는 오프셋만 변경되므로 세그먼트 경계를 넘어 접근할 수 없다는 점이 가장 큰 차이입니다.

예제 프로그램

#include <stdio.h>
int main(){
    char huge **ptr;
    printf("%d %d %d", sizeof(ptr), sizeof(*ptr), sizeof(**ptr));
    return 0;
}

실행 결과

4 4 1

ptr 자체는 32비트(4바이트) 거대 포인터이고, *ptr 역시 4바이트 크기의 거대 포인터이며, **ptr은 실제 문자(char) 데이터이므로 1바이트입니다.

정리

근거리·원거리·거대 포인터는 16비트 x86 환경(DOS 시대)의 세그먼트:오프셋 메모리 구조에서 사용되던 개념입니다. 현대의 32비트·64비트 시스템은 플랫(flat) 메모리 모델을 사용하기 때문에 이러한 구분이 필요 없지만, 레거시 코드나 임베디드 시스템을 다룰 때는 여전히 알아두어야 할 중요한 개념입니다.