About C – “포인터(Pointer), 주솟값, 포인터 변수, null포인터와 void포인터”

About C – “포인터(Pointer), 주솟값, 포인터 변수, null포인터와 void포인터”

10월 1, 2021

포인터(=포인터 변수) 란?

포인터는 다른 언어와 차별되는 C언어만의 가장 큰 특징 중 하나입니다. 포인터를 이용하게 되면, 기계어나 어셈블리 언어처럼 메모리의 주소를 이용해 메모리의 내용을 직접 접근할 수 있다는 장점이 있죠.

메모리에는 위치를 구분하기 위해 순서대로 번호가 붙어있는데, 이것을 메모리의 주소(address) 라고 합니다. 예컨대 int a = 0; 처럼, 변수를 초기화하면서 선언하면 4바이트의 메모리 공간이 확보되고 초기값인 0이 할당되겠지요. 실제로, & 연산자를 활용하여 변수가 기억되어 있는 메모리 주소를 알 수 있습니다.

#include <stdio.h>

int main() {
	int a = 1;
	printf("%p",&a); // a가 저장되어 있는 메모리 주소를 알 수 있습니다.
}

포인터(포인터 변수)란 이 메모리 주소값을 저장하는 변수입니다.

포인터의 선언

포인터 또한 변수이므로 사용하기 전에 선언이 필요합니다. 간단하게, 자료형과 변수명 사이에 * 을 더 써 주면 됩니다. int *x; 나, int* y 처럼 말이지요.
포인터는 주소값을 저장하기 위해서 사용하는 변수라고 말씀드렸습니다. 포인터에 주소를 대입하는 방법은, 주소 연산자인 &을 활용해 해당 변수의 주소를 저장하면 됩니다.

#include <stdio.h>

int main() {
	int a = 1, *pa;
    pa = &a; // 포인터 pa에게 a의 메모리 주솟값을 대입했습니다.
}

위의 코드대로라면 포인터 pa에는 변수 a의 주소가 들어있습니다. pa가 저장하고 있는 a의 주소로 가서, 그 값을 변수 b에 대입하기 위해서는 다음과 같이 하면 됩니다.

#include <stdio.h>

int main() {
	int a = 1, b, *pa;
    pa = &a; // 포인터 pa는 a의 주솟값을 가지고 있습니다.
    b = *pa; // 실행문에서의 *는 참조 연산자이고, 포인터의 주소로 가서 값을 가져옵니다.
    printf("%d",b); // 1
}

여기서, 선언문에서의 *와 실행문에서의 *의 차이를 짚고 넘어가겠습니다.

선언문에서의 *는 -> 포인터를 선언할 때 사용합니다. (구두점으로서 사용합니다.)

실행문에서의 *는 -> 주소로 가서 값을 가져올 때 사용합니다. (연산자로서 사용합니다.)

int x = 5, y;
int *px; // 포인터 px의 "선언"입니다. 선언문에서의 *
px = &x; // x의 주소를 포인터 변수 px에 대입하였습니다.
y = *px; // px가 저장하고 있는 주소로 가서 값을 얻어옵니다. 실행문에서의 *이고, 참조 연산자로 사용됩니다.
*px = 100; // 포인터 px가 가르키는 주소에 100을 대입했습니다. px가 x의 메모리 주소를 가지고 있으므로, 변수 x의 값도 바뀔 것입니다. 주소로 가서 값을 바꾸는 간접적인 방법으로 값을 변경했습니다.

포인터 변수의 자료형

자료형 *포인터변수명 입니다. 예를 들어, int *pi 는 변수 pi int형 데이터를 참조하기 위한 포인터 변수를 나타냅니다. pi가 지시하는 곳의 자료형이 int형이라는 것입니다. pi가 지시하는 곳의 자료형이 int이기 때문에, int형의 주소만 대입할 수 있습니다. char형이나, double형 변수의 주소를 pi에 대입할 수 없다는 것입니다.

NULL 포인터

  • 초기화된 주소가 NULL인경우, NULL 포인터라 하고 그것은 0번지를 가리키고 있습니다.
  • NULL은 stdio.h에 0으로 정의되어 있습니다.
  • 0번지는 메모리 공간의 제일 처음에 해당되는데, OS에 의해서 이 번지에는 읽기 쓰기가 불가능하도록 보호되고 있습니다.
  • 그래서, 실제로 포인터가 0번지를 가리키는 상황은 발생하지 않고 오류가 발생한 경우를 나타낼 때 더 많이 사용합니다.
  • 포인터를 리턴하는 대부분의 함수는 함수 실행이 실패했을 때 NULL값을 리턴합니다.
  • 파일을 열 때 사용하는 fopen() 과 같은 함수는 파일을 개방하지 못하면 NULL포인터를 리턴합니다. 이를 통해서 오류 메시지가 나오도록 코드를 작성할 수 있겠습니다.

void형 포인터

  • 가리키고 있는 대상체가 정해져 있지 않아, 어느 것이나 가리킬 수 있는 포인터를 말합니다.
  • 예를 들면 int *pi 에서는 *pi에 정수형 주소만 대입이 가능합니다. 하지만 어떤 자료형도 형 변환 없이 void형 포인터에 대입이 가능합니다.
  • 임의의 포인터에 void형 포인터를 대입할 때에는, cast 연산자를 사용해야 합니다.

제가 이해한 간략한 포인터 정리입니다.

Leave A Comment

Avada Programmer

Hello! We are a group of skilled developers and programmers.

Hello! We are a group of skilled developers and programmers.

We have experience in working with different platforms, systems, and devices to create products that are compatible and accessible.