메모리의 구조

우리는 익히 char형에 대한 크기는 1바이트, int 형의 크기는 4바이트 double형이면 8바이트라고 알고있다.

컴퓨터는 이러한 입력들을 제어하기 위해 주소값이라는 독특한 방식을 사용한다.

주소값은 0x로 시작하는 형태인데, 각 변수 선언의 자료형 별 크기에 따라 바이트 크기만큼 주소값을 차지게하게 되는 방식이다.

우리가 앞으로 공부할 포인터는 바로 이 주소값의 개념을 활용한 독특한 방식이다.

기본적인 선언법

포인터 선언의 기본 형태는

자료형 *변수명;

이다.

포인터의 크기

그렇다면 포인터의 크기는 몇 바이트일까?

보통 위의 설명을 읽은 사람이라면, 자료형의 크기와 포인터의 크기는 일치하다고 착각하기 쉽다.

그러나, 포인터의 크기는 사실 32비트 프로그램 컴파일 기준 4바이트 이다.

왜 그럴까

아주 간단하게 설명하자면, 그것이 32비트 시스템(특히 우리가 표준이라고 생각하는 인텔 아키텍처)에서의 표준이기 때문이고 좀 더 복잡하게 설명하자면 포인터는 가용가능한 모든 메모리의 경우의 수를 표현해주어야하기 때문이다.

32비트 컴퓨터가 가질 수 있는 메모리 주소의 범위는 2의 32승 -1까지이다.

즉 주소 범위는 시스템의 비트수와 비례한다.

그리고 포인터는 이 모든 주소를 나타내주어야하는데, 사실 저 메모리의 크기는 4gb이기 때문에 우리는 자료형 하나에 4gb를 할당하는 것이 아닌 자료형의 단위인 바이트를 사용하여 포인터의 크기를 4바이트로 지정한것이다.

포인터의 사용법 및 특징

선언법은 우리가 위에서 사용한 것과 동일하다.

그러나 c언어에서는 어떤 변수를 지역변수로 사용할 때에는 무조건 초기화 과정을 거쳐주어야하는데 이는 포인터 변수에게도 똑같이 적용된다.

따라서 포인터 사용을 위한 진짜 포인터 변수 선언법은 다음과 같다.

자료형 *변수명=&찾고자하는 주소를 가진 변수;

포인터 변수의 내용 출력하기

포인터 변수를 선언한 뒤 내용물을 출력하기 위해서는 *포인터 변수명을 활용하는 것을 알 수 있다.

이는 포인터 변수가 가리키는 메모리 주소에 저장된 값을 읽어오겠다는 약속으로 *이 어디에 붙느냐에 따라 포인터 변수임을 명시하기도 하고, 메모리 주소에 저장된 값을 읽어오라는 신호이기도 함을 알 수 있다.

주소값? 내용물

내용물을 출력하고 싶을 경우(주소값 안에 담겨있는 변수의 내용)

printf("*포인터 변수명=%d\n",*포인터 변수명);
  • 주소값 자체 출력하기

    printf("포인터 변수명=%x\n",포인터 변수명);
    

포인터의 연산

자, 포인터 연산에서는 덧셈은 의미가 없고 뺄셈만이 의미를 가지게 된다.  <br>
  
주소값을 나타내는 포인터의 특성상 연속적으로 적재된 메모리라고 가정하여도 그 메모리의 주소값을 더하는 행위가 우리가 하고자하는 산술적인 덧셈이라는 행위의 결과물과 아무런 연관성을 가지지 못하기 때문이다. <br> 
  
그에 비해 뺄셈의 경우, 거리를 의미할 수 있기 때문에 하나의 배열 내에서 두 데이터가 얼마나 멀리 떨여짔는가 혹은 배열의 크기가 어떻게 되는지 등을 파악하는 데에 사용할 수 있다.<br>

유의점: 포인터간의 뺄셈 역시 내가 말한 것과 같은 유의미한 결과를 얻기 위해서는 같은 배열 내에 위치해야하며, 타입 역시 같아야한다.

예외점

그러나, 포인터의 덧셈이 유의미하게 사용될 때도 있는데 바로 포인터에 또다른 정수를 더하는 경우이다.

이 경우에는 거리만큼 이동이 가능하기 때문인데, 간단하게 설명하면 주소값에다가 1을 더할 경우 기존 주소에서 단순히 주소값을 1만 늘려주는 것이 아니라 그 다음 주소값만큼으로 이동을 하는 원리로 덧셈이 작동하기 때문이다.

즉 포인터와 정수를 더하게 되면 sizeof의 개념으로 각 자료형에 알맞는 크기만큼 더하기 된 이후 주소값이 이동되는 것이다.

#include<stdio.h>
int main() {
    int array[5] = { 1, 2, 3, 4, 5 };
    int* ptr = &array[0]; // 배열의 첫 번째 요소를 가리키는 포인터 ptr
    ptr += 5 / 2;
    int middle_element = *ptr;
    printf("%d\n", middle_element);
}

위 코드를 보면 알 수 있듯, 포인터를 5개만큼 이동시키고 나누기 2를 해주면 가운데 요소인 3이 출력된다.

포인터의 자료형이 다양한 이유

얼핏 생각했을 때에는 포인터의 크기는 내용물에 상관없이 4바이트면서 왜 포인터에는 자료형이 존재해야하는가라는 의문을 품을 수 있다.

포인터는 일종의 간접 참조 형태로 작동하기 때문에, 포인터의 크기와 별개로 주소가 가지고 있는 공간의 크기는 제각각이기 때문이다.

태그:

카테고리:

업데이트:

댓글남기기