포인터란? - call by reference와 call by value의 차이
C언어의 화룡점정. 포인터!
아무튼 C언어에 대해 한번이라도 공부를 해보았다면 다들 포인터가 어렵다고 말한다. (필자 또한 마찬가지) 그래도 전공 수업들을 진행해나가다보면 포인터에 대해 어렴풋이 알 수 있었다. 이번에는 아예 확실히 포스팅해서 잡아보도록 하겠다!
포인터란 무엇일까?
포인터(Pointer)는 말 그대로 어떤 것을 가리키는 것을 의미한다. 즉, 포인터는 "주소"를 가리킨다. 이름만 포인터라고 말할 뿐이지 포인터도 int, char와 같이 다를 바 없는 변수이다. 그래서 포인터 변수라고 부른다. 포인터는 주소를 가리키기에 주소 값을 저장한다.
아래 예시 코드를 한번 보자.
#include <stdio.h>
int main(){
int *p = NULL;
int num = 15;
p = #
printf("int 변수 num의 주소 : %d \n", &num);
printf("포인터 p의 값 : %d \n", p);
printf("포인터 p가 가리키는 값 : %d \n", *p);
return 0;
}
결과 값은 아래와 같다.
int 변수 num의 주소 : -515017028
포인터 p의 값 : -515017028
포인터 p가 가리키는 값 : 15
이와 같이 포인터 변수를 선언할 때에는 담고자 하는 자료형에 * (참조 연산자)를 붙여서 선언한다. int 형의 주소를 담고싶다면 int*, char형의 변수의 주소를 담고싶다면 char*을 사용한다.
하지만 그렇다고 포인터 변수의 크기가 달라지진 않는다. 동일한 운영체제 시스템일 경우 주소값이 동일한 크기를 갖기 때문이다. (하드웨어적으로 그렇다! 32비트 시스템이면 4바이트, 64비트 시스템이면 8바이트). 자료형에 따라 선언하는 자료형이 달라지는 이유는 가리킬 주소가 어떤 자료형을 갖는지 알려주기 위해서 그렇다. 포인터 연산을 할 때에는 그 주소로 찾아가 int형이면 4바이트만큼, double형이면 8바이트씩 읽어들여야 한다. 따라서 어떤 자료형의 주소를 가리키는지 알려주어야 하는 것이다. 복잡할 것 없이, 가리키는 변수에 맞춰 포인터 변수도 자료형을 맞춰준다고 생각하면 된다.
하나 코딩 잘하는 팁을 풀자면, 포인터를 처음 선언할 때 NULL로 초기화를 해주는 것이 좋다. C언어에서는 변수를 초기화 하지 않았을 때 초기값에는 쓰레기 값이 들어있다. 포인터 변수도 이는 마찬가지인데, 특히 포인터는 주소값을 다루기 때문에 초기화를 하지 않고 사용하다가 실수라도 일어나면.. 에러 찾기도 힘들고 그렇다. 선언 후 바로 다른 변수의 주소값을 넣더라도 되도록이면 NULL로 초기화를 시켜주는 것이 좋다.
이제 선언한 포인터에 num 변수의 주소값을 담을 때에는 num 앞에 & (주소연산자)를 붙여주어야 한다.
위를 보면 좀 더 이해가 잘 될 것 같다. *p에는 포인터 변수가 가리키는 주소에 들어있는 변수의 "값"이 들어있다. p에는 "주소"가 들어있는 것이다! (프로그램 코드의 결과값을 보면 느낌이 올 것이다.) 즉, *p 라고 써버리면 그냥.. int나 double형과 같이 덧셈 뺄셈, 곱셈등을 다 할 수 있다.
알고 보면 쉬운 참조연산자
코딩할 때, 괜시리 * 만 보면 약간 겁을 먹게 된다... 하지만 겁먹을 필요가 정말 하나도 없다~
아래 예시를 보면 참조연산자에 대한 이해가 좀 더 잘 될 것이다.
#include <stdio.h>
int main(){
int *p = NULL;
int num = 10;
p = #
printf("포인터 p가 가리키는 값 : %d\n", *p);
printf("num의 값 : %d\n\n",num);
*p += 5;
printf("포인터 p가 가리키는 값 : %d\n", *p);
printf("num의 값 : %d\n\n",num);
(*p)++;
printf("포인터 p가 가리키는 값 : %d\n", *p);
printf("num의 값 : %d\n\n",num);
*p++;
printf("포인터 p가 가리키는 값 : %d\n", *p);
printf("num의 값 : %d\n\n",num);
return 0;
}
결과는 아래와 같다.
포인터 p가 가리키는 값 : 10
num의 값 : 10
포인터 p가 가리키는 값 : 15
num의 값 : 15
포인터 p가 가리키는 값 : 16
num의 값 : 16
포인터 p가 가리키는 값 : -540211520
num의 값 : 16
*p += 5일 때를 보자. 포인터 변수는 포인터 p가 가리키는 변수로 가서, 그 주소에 들어있는 값을 증가시킨다. * 연산자가 붙으면 그 주소로 찾아간다고 생각하면 된다.
다만, *p++을 생각해보자 (솔직히 누가 이렇게 코딩하면.. 할말하않.. 다들 안하실거라 믿는다). 여기서 * 참조 연산자는 ++ 증감 연산자에게 우선순위가 밀린다.. 그래서 *p++의 경우 변수 p를 먼저 증가시킨다. 증가한 그 주소에는 아무것도 선언되어 있지 않아서 쓰레기 값이 들어있어 이상한 값이 출력되는 것이다.
Call by value와 Call by reference
시험 단골 문제인 콜바이벨류 콜바이레퍼런스..
인자를 전달하는 방식에는 두가지가 있다. 바로 Call by value와 Call by reference이다.
Call by value
기본적으로 C언어에서 지원하는 방식으로, 이 전까지 우리가 계속 사용해왔던 일반적인 함수들은 이렇게 전달한다. 함수에서 값을 복사해서 전달하는 방식으로, 인자로 전달되는 변수를 함수의 매개변수에 복사한다. 원본 값을 바꿀 필요가 없는 경우에는 대게 call by value 형식을 사용하면 된다.
Call by reference
함수에서 값을 전달하는 대신 주소값을 전달하는 방식을 call by reference라고 한다.
사실 엄밀히 말하자면, C언어에서의 방식은 주소값 자체를 복사해서 넘겨주는 것이므로 call by value이다. 또한 이렇게 주소값을 복사해서 넘겨주는 것을 call by address 방식이라고 한다. C언어에서는 call by reference를 공식적으로 지원하지 않는다. 그러나 의미적, 결과적으로 call by address 를 이용해서 call by reference와 같이 사용할 수 있기 때문에 일반적으로 C언어에서 포인터를 이용해 주소값을 넘겨주는 방식을 call by reference라고 설명한다.
SWAP 예시
call by value와 call by reference를 사용할 때의 swap 코드 예시를 한번 보도록 하자.
#include <stdio.h>
//call by value
void swap1(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
}
//call by reference
void swap2(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main(){
int a=10, b=50;
printf("call by value\n");
swap1(a, b);
printf("결과 a : %d, b : %d\n\n", a, b);
printf("call by refernce\n");
swap2(&a, &b);
printf("결과 a : %d, b : %d\n\n", a, b);
return 0;
}
아래는 수행 결과이다.
call by value
결과 a : 10, b : 50
call by refernce
결과 a : 50, b : 10
이렇게 call by reference 함수를 사용하면 원래 변수의 값도 바뀌게 된다!
'Computer Engineering > C' 카테고리의 다른 글
C 언어 : 문자 처리 함수 (0) | 2018.12.15 |
---|---|
C 언어 : 문자열 변환 라이브러리 함수 (0) | 2018.12.15 |
C언어 : 특정 단어가 입력될 때 까지 단어를 입력받기 (0) | 2018.12.15 |
문자열 처리 함수 strlen과 strcpy 만들기 (0) | 2018.12.15 |
C언어 : 스택(stack) , 배열을 사용해 스택 구현하기 (0) | 2018.12.15 |
댓글
이 글 공유하기
다른 글
-
C 언어 : 문자 처리 함수
C 언어 : 문자 처리 함수
2018.12.15 -
C 언어 : 문자열 변환 라이브러리 함수
C 언어 : 문자열 변환 라이브러리 함수
2018.12.15 -
C언어 : 특정 단어가 입력될 때 까지 단어를 입력받기
C언어 : 특정 단어가 입력될 때 까지 단어를 입력받기
2018.12.15 -
문자열 처리 함수 strlen과 strcpy 만들기
문자열 처리 함수 strlen과 strcpy 만들기
2018.12.15