본문 바로가기
C/Definition&Grammar

[C] 포인터 (Pointer)

by 꾸압 2021. 3. 9.

◆ 자료를 변수에 저장 시, 컴퓨터가 사용 가능한 메모리 공간의 특정 주소에 자료형 크기만큼 공간을 할당받아 저장시킨다. 이렇게 자료가 저장된 위치가 '메모리 주소'다.

포인터는 이런 '메모리 주소'를 참조한다.

◆ 함수 간 데이터 공유하는 방법으론 

void show (매개변수) {
	
    리턴
}

매개 변수를 활용하거나 리턴 값을 받아 쓰는 것이다. 문제는 리턴 값이 1개 밖에 안되므로 이에 대안으로 포인터를 사용 가능하다.

 

<예제.1>

#include <stdio.h>

int main(){
	
	int a = 10;		// 주소 값
	int *pA = NUll;		
	
	pA = &a;	// 주소 값을 저장 
	*pA = 20;	// 주소값을 찾아가는 데이터 값 
	
	printf("%d", a);
	
	return 0;
} 

- 포인터 변수는 처음에 항상 NULL값을 줘야함
- 포인터의 자료형과 이용하고자 하는 주소값(변수) 의 자료형(int 면 int, double 이면 double) 은 반드시 같아야 함

 

<예제.2>

#include <stdio.h>

int main(){
	
	int a = 10;
    
	int *p1, p2, p3;	
	
	printf("%d", a);
	
	return 0;
} 

포인터를 여러개 사용하고자 할 때 이렇게 포인터를 설정하면 * 이 붙은 *p1 만 포인터 기능을 하고, 나머지 p2 - p3 는 일반 int 변수 기능을 한다.

#include <stdio.h>

int main(){
	
	int a = 10;
    
	int *p1 = NULL, *p2 = NULL, *p3 = NULL;	
	
	printf("%d", a);
	
	return 0;
} 

제대로 사용하려면 위와 같이 모든 포인터 변수에 * 을 붙이고 반드시 NULL 값을 넣어 초기화 시킨다.

 

<예제.3>

#include <stdio.h>

int main(){
	
	int *p = NULL;
	
	*p = 1234;
	
	return 0;
} 

C언어 메모리 권한은 '컴파일러' 에 있다. 사용자(USER)가 강제로 포인터에 값을 넣는건 권한을 넘는 행위이므로 잘못되었다.

포인터는 반드시 주소값을 가진 변수를 통해야 한다.

 

<예제.4>

#include <stdio.h>

int main(){
	
	int *p = NULL;
	int a;
	
	if(p != NULL){
		printf(" 동작 가능! \n");
	} 
	
	else {
		printf(" NULL 값 아님. 동작 불가 \n");
	} 
	
	return 0;
} 

포인터 변수 사용시 반드시 NULL 값인지 아닌지 확인 하는 '오류처리문' 을 만들어야 한다.

 

<예제.5>

#include <stdio.h>

int main(){

	int a[5] = {1, 2, 3, 4, 5};		// 배열
	int *p = NULL;
	
	p = a;	 
	
	int i;
	
	for(i=0; i<5; i++){
		printf("%d", p[i] );
	} 

	return 0;
}

배열은 포인터 사용시 예외로 '&' 를 쓰지 않는다. (일반 변수는 &a를 사용)

◆ 포인터는 배열이고 배열은 포인터 인 셈.

 

<예제.6>

#include <stdio.h>

int main(){

	int a[5] = {1, 2, 3, 4, 5};		// 배열 ==> 포인터 
	int *p = NULL;		// 포인터 
	
	p = a;	// 포인터 ==> 배열 
	
	printf("%d \n", &a[0] );
	printf("%d \n", &a[1] );
	printf("%d \n", &a[2] );
	printf("%d \n", &a[3] );
	printf("%d \n", &a[4] );
	
	printf("%d \n", (p) );
	printf("%d \n", (p+1) );
	printf("%d \n", (p+2) );
	printf("%d \n", (p+3) );
	printf("%d \n", (p+4) );
	
	return 0;
}

배열과 포인터를 연결시켜 사용한 예시다. 출력하면 '주소값' 이 출력된다. 

포인터가 연결된 배열은 '&' 를 붙여선 안되고, 배열과 연결된 포인터는 ' * ' 를 붙여야만 자료값이 정상 출력된다.

 

<예제.7>

#include <stdio.h>

int main(){

	int a[5] = {1, 2, 3, 4, 5};		// 배열 ==> 포인터 
	int *p = NULL;		// 포인터 
	
	p = a;	// 포인터 ==> 배열 
	
	printf("%d \n", a[0] );
	printf("%d \n", a[1] );
	printf("%d \n", a[2] );
	printf("%d \n", a[3] );
	printf("%d \n", a[4] );
	
	printf("%d \n", *(p) );
	printf("%d \n", *(p+1) );
	printf("%d \n", *(p+2) );
	printf("%d \n", *(p+3) );
	printf("%d \n", *(p+4) );
	
	return 0;
}

*(p+number) 하나하나가 배열의 각 원소를 가리키며, a[number] 는 배열 내 자료값을 정상 출력한다.

 

<예제.8>

#include <stdio.h>

int main(){

	int a[5] = {1, 2, 3, 4, 5};		// 배열
	int *p = NULL;
	
	p = a;	// 포인터 ==> 배열 
	
	int i;
	
	for(i=0; i<5; i++){
		
		printf("%d", a[i] );	// 배열 
		printf("%d", *(a+i) );	// 배열 ==> 포인터 
		printf("%d", *(p+i) );	// 포인터 
		printf("%d", p[i] );	// 포인터 ==> 배열 
	} 

	return 0;
}

포인터를 배열과 같은 기능으로 사용하는 예시. 4가지 모두 같은 기능을 한다.

 

 

◆ 참조

v = *p++  : p가 가리키는 값을 v에 대입한 후 p를 증가

v = (*p)++  : p가 가리키는 값을 v에 대입한 후, p가 가리키는 값을 증가

v = *++p  : p를 증가시킨 후, p가 가리키는 값을 v에 대입

v = ++*p  : p가 가리키는 값을 가져온 후, 그 값을 증가시켜 v에 대입

 

<예제.9>

#include <stdio.h>

int main(){
	
	int i = 100;
	int *p = &i;
	int **q = &p;
	
	printf("%d \n", i);
	
	*p = 200;
	printf("%d \n", i);
	
	**q = 300;
	printf("%d \n", i);
	
	return 0;
} 

포인터를 2번 활용하여 자료를 숨기도록 하였다.

 

<예제.10>

#include <stdio.h>

int main(){
	
	int a=10, b=20, c=30;
	
	int *pABC[3] = { &a, &b, &c };
	
	printf("%d \n", pABC[0] );
	printf("%d \n", pABC[1] );
	printf("%d \n", pABC[2] ); 
	
	return 0;
}

포인터를 배열로도 만들 수 있다.

'C > Definition&Grammar' 카테고리의 다른 글

[C] 그래프 알고리즘 (Graph Algorithm)  (0) 2021.03.11
[C] 삽입 / 선택 / 버블 정렬  (0) 2021.03.10
[C] C 라이브러리  (0) 2021.03.09
[C] 표준 라이브러리 함수  (0) 2021.03.08

댓글