DNF LOVE
C/C++ Pointer 개념과 실행 예제 본문
C와 C++의 가장 큰 장점이자 특징은 무엇일까? 그것은 바로 메모리 관리를 개발자가 직접한다는 것이다.
JAVA와 C#같은 경우는 각각 JVM, .Net 의 VM에 의해 GC가 관리된다.
그러나 C와 C++은 각각 malloc / new 연산자를 통해 메모리를 할당하고 delete를 사용하여 메모리를 해제한다. 이를 동적할당이라 한다.
프로그램이 변수를 인스턴스화(메모리에 데이터를 할당하여 사용할 수 있도록 함) 할 때 사용 가능한 메모리 주소가 변수에 자동으로 할당되고(OS의 몫) 변수에 할당된 값은 이 메모리 주소에 저장된다.
메모리 관리를 개발자가 직접하기 때문에, JAVA와 c#과 다르게 C와 C++에서는 메모리에 직접 다가가는 포인터 개념을 사용한다.
포인터란? 어떠한 값을 저장하는 것이 아닌 어떠한 값의 주소(=인스턴스화 할 때 할당되는 메모리 주소)를 저장하는 것이다.
포인터를 사용하는 이유는 다양하다.
- 포인터는 배열을 반복할 때 사용할 수 있다 - 배열 인덱스 대신 사용이 가능하다.
- C++에서 동적으로 메모리를 할당하는 방법이다.
- 데이터를 복사하지 않고도 많은 양의 데이터를 함수에 전달할 수 있다.
- 상속을 다룰 때 다형성을 달성하기 위해 사용한다.
- 연결리스트 및 트리와 같은 자료구조에서 체인을 형성하는데 사용할 수 있다.
아래부터는 포인터 개념에 사용되는 연산자(&, *)를 사용하여 다양한 예시를 보여주도록 하겠다.
1. 주소연산자(The Address-of Operator, &) : 주소연산자를 사용하면 변수에 할당된 메모리 주소를 확인할 수 있다.
#include <iostream>
using namespace std;
int main()
{
int value = 10;
cout << value << endl;
cout << &value << endl;
return 0;
}
여기서 10은 정수형 변수 value 가 갖고있는 데이터 값이며 002AF8B4는 OS가 value게 할당해준 메모리 주소를 가리킨다.
이 메모리 주소를 참고하고자 할 때 주소 연산자&를 사용한다.
2. 역참조 연산자(The dereference operator, *) : 역참조 연산자를 사용하면 특정 주소에서 값에 접근할 수 있다.
#include "pch.h"
#include <iostream>
using namespace std;
int main()
{
int value = 10;
cout << value << endl;
cout << &value << endl;
// cout << *value << endl;
cout << *&value << endl;
return 0;
}
일반 변수로 선언한 value는 역참조 연산자 혼자서는 사용을 못하고, *&value로 주소연산자와 함께 써야 한다. 특정 주소(value의 주소)를 참조하여 데이터 값을 찾아간다는 뜻이기 때문이다.
** 역참조 연산자는 단항 연산자(부호 연산자, 증감 연산자, 형변환 연산자와 같은 피 연산자가 1개인 연산자)이며, 곱셈 연산자는 이항 연산자(피 연산자가 2개인 연산자)이다.
3. 포인터(Pointer) : 어떠한 값을 저장하는 것이 아닌 메모리 주소를 저장하는 '변수'이다.
#include "pch.h"
#include <iostream>
using namespace std;
int main()
{
int value = 10;
int *ptr; // 포인터 변수 ptr 선언
ptr = &value; // 포인터 변수 ptr에 value의 메모리 값으로 초기화한다.
// 포인터 변수는 데이터 값이 아니라 메모리 값을 참조하여 넣는다.
cout << value << endl;
cout << &value << endl;
cout << *ptr << endl;
cout << ptr << endl;
cout << &ptr << endl;
return 0;
}
value : 각각 정수형 변수 value의 데이터 10을 출력한다.
&value : 정수형 변수 value가 갖고있는 메모리 주소를 출력한다.
*ptr : value의 메모리 주소를 갖고 있는 포인터 변수 ptr을 역참조하여 ptr이 가리키는 데이터 값을 출력한다.(ptr의 데이터 값 = value의 메모리 주소, 이 value의 메모리 주소를 역참조 = value가 가리키는 값)
ptr : ptr이 담고 있는 value 메모리 주소를 출력한다.
&ptr : value의 메모리 주소와 ptr의 메모리 주소는 독립적이기 때문에 ptr이 할당받은 메모리 주소값을 출력한다.
** 단, C++에서는 포인터에 리터럴 메모리 주소를 직접 할당할 수는 없다.
#include <iostream>
using namespace std;
int main()
{
int value = 10;
int *ptr;
ptr = &value;
*ptr = 5;
cout << value << endl;
cout << *ptr << endl;
return 0;
}
- 포인터 변수 ptr에 value 메모리 값을 참조하도록 하였다.
이때, ptr를 역참조하여(ptr이 가리키는 메모리 값의 데이터 값 참조) 5로 바꾸어주었다.
그러고 value와 *ptr은 둘 다 전부 값이 5로 출력되었다.
이는 왜 이렇게 되는 것일까? 바로 Call By Reference 성질에 의한 것이다.
프로그래밍 언어를 공부하면서 기본적으로 배운 내용 중 [call by reference], [call by value]일 것이다. 이들의 차이점과 설명은 다음 포스터에서 마저 설명하도록 하겠다.
'Programming > C++' 카테고리의 다른 글
C++ 문법> String to char, char to String 형변환 (0) | 2019.10.23 |
---|---|
c++> int to string(int -> string), string to int(string -> int) 형변환 (0) | 2019.10.23 |
c++의 형변환(Typecasting) 몇 가지(reinterpret_cast, static_cast) (0) | 2019.10.23 |
C++에서 <algorithm>을 사용하여 정렬을 해보도록 하자. (0) | 2019.10.23 |
함수 호출> Call By Reference 와 Call By Value에 대한 차이점과 설명 (0) | 2019.10.22 |