C

[내배캠자습]C언어 챕터 7-3 : NULL과 void 포인터

BreadMushroom 2026. 3. 29. 15:22

포인터를 초기화 하려면 어떻게 하면 될까요?

변수를 초기화 할 때는 대부분 0으로 초기화를 했습니다. 포인터도 변수이긴 한데, 0처럼 깔끔하게 초기화하는 그런 값이 없을까요?

NULL 포인터

#define NULL ((void*)0) 아무것도 가르키지 않는 포인터.

Ex070301) NULL을 활용한 포인터 유효성 검사

아래 소스코드를 따라서 작성해봅시다. 따라 적은 코드의 출력 결과를 예측해보고, 예측 결과와 실행 결과를 비교해봅시다.

// Main.c

#include <stdio.h>

int main(void)
{
	int* Ptr = NULL;

	if (NULL == Ptr)
	{
		printf("NULL == Ptr");
	}

	if (Ptr != NULL)
	{
		printf("Ptr is not the \\"NULL pointer\\"\\n");
	}

	/* 간혹 다음과 같이 쓰기도 합니다. worst.*/
	if (Ptr)
	{
		printf("Ptr is not the \\"NULL pointer\\"\\n");
	}

	/* 올바르지 않은 예들. 명시적인 부분에서 올바르지 않음. */
	if (0 == Ptr)
	{
		printf("Ptr is the \\"NULL pointer\\"\\n");
	}
	if (Ptr != 0)
	{
		printf("Ptr is not the \\"NULL pointer\\"\\n");
	}

	return 0;
}

NULL 포인터의 쓰임새

1️⃣

포인터의 초기화

2️⃣

포인터가 더이상 사용중이지 않음을 알리고 싶을 때.

3️⃣

포인터가 유효한 메모리 주소를 저장하고 있는지 확인할 때.

Ptr = NULL;

if (NULL == Ptr) 
{ 
	/* alert */ 
}

자료형이 정해지지 않은 포인터

다시 한 번 포인터 선언 및 초기화 코드를 살펴봅시다. 자료형* 변수명 = 메모리주소값; NULL 포인터는 메모리주소값이 아직 정해지지 않았을 때 사용 했습니다. 자료형을 지금 바로 정할 수 없을 때도 있습니다.

void 포인터

범용 포인터라고도 부릅니다. void* 변수명 = 메모리 주소 값;

어떤 자료형의 포인터라도 void*에 대입 가능합니다.

즉, 매개변수 자료형으로 void*를 사용하면, 어떤 자료형의 포인터라도 모두 받을 수 있는 함수입니다.

 

void 포인터의 주의점

1️⃣

void*에 역참조 연산은 불가능. 해당 메모리 주소부터 몇 바이트만큼 읽어야 내 데이터인지 모르기 때문입니다.

2️⃣

void*에 정수를 더하거나 빼는 연산은 불가능. 해당 메모리 주소부터 몇 바이트만큼 더하거나 빼야하는지 모르기 때문입니다.

 

Ex070302) void*와 역참조

아래 소스코드를 따라서 작성해봅시다. 따라 적은 코드의 출력 결과를 예측해보고, 예측 결과와 실행 결과를 비교해봅시다. 만약 컴파일 에러가 난다면 어디서 왜 나는지 생각해봅시다.

// Main.c

#include <stdio.h>

int main(void)
{
	float PI = 3.14f, Result;
	void* p;
	float* q;

	p = &PI;
	q = p;

	printf("%f\\n", *p);
	printf("%f\\n", *(float*)p);

	Result = *p + *q;
	Result = *(float*)p + *q;
	printf("%f\\n", Result);

	return 0;
}

문제점:
printf("%f\\n", *p);
포인터 p는 자료형이 void이기 때문에 역참조 연산자를 사용할 수 없다.
자료형이 void이면 주소를 알아도 몇 바이트인지 크기를 몰라서 연산할 수 없기 때문이다.
q = p;
포인터 q의 자료형이 float이니 대입할 거면 (float*)p로 형변환을 해줘야됨