< 포인터 > 

▶ 포인터란?

- 변수의 메모리 공간주소를 가리키는 변수

- 포인트 변수의 크기는 무조건 4byte이다.

- 포인터 선언 :  '*' 를 붙여준다.

                        → 선언 방식 : 자료형 * 포인터 변수 이름;

- 포인터 초기화 : 변수 이름 앞에 '&'를 붙여준다.

                           ※ 배열의 이름은 그 자체가 주소이므로 '&'를 붙이지 않는다.

 

< 변수인 경우 > < 배열인 경우 >
int a;
int* p;
p = &a
int a [10];
int* p;
p = a;

- 포인터 변수에는 변수의 주소가 들어간다.

- 포인터를 이용하면 메모리에 직접접근이 가능하고 함수를 넘나들어 사용할 수 있게 된다.

- 포인터 활용

char ch; // 문자형 변수 선언, 1byte 차지

char* p; // 포인터 변수 선언, 4byte 차지

ch = 'A'; // 문자형 변수에 문자 'A' 대입

p = &ch; // 포인터 변수에 변수 ch의 주소인 '&ch' 대입

- 포인터가 유용한 경우

  • 배열은 포인터를 사용하여 구현된다. 포인터는 배열을 반복할 때 사용할 수 있다. (배열 인덱스 대신 사용 가능)
  • C++에서 동적으로 메모리를 할당할 수 있는 유일한 방법이다. (가장 흔한 사용 사례)
  • 데이터를 복사하지 않고도 많은 양의 데이터를 함수에 전달할 수 있다.
  • 함수를 매개 변수로 다른 함수에 전달하는 데 사용할 수 있다.
  • 상속을 다룰 때 다형성을 달성하기 위해 사용한다.
  • 하나의 구조체/클래스 포인터를 다른 구조체/클래스에 두어 체인을 형성하는 데 사용할 수 있다. 

 

▶ 간접 참조 연산자

- 지정된 주소에 있는 값을 액세스하는 연산자

- 역 참조 연산자, 간접 연산자, * 연산자라고도 한다.

- 피연산자의 메모리에 접근하여 주소 값을 저장해가는 변수

- ex) a의 주소를 100번지를 가리킨다고 가정하자.

 

int a = 200;
int* p;
p = &a;

cout << p; // 이 경우 a의 주소값인 100이 출력됨
cout << *p; // 이 경우 a의 값인 200이 출력됨

위의 표처럼 포인터 변수 앞에 '*' 을 붙여주어야 값이 출력된다.

 

▶ 포인터 연산

- 포인터 연산 규칙

① 포인터끼리 더할 수 없다. ( 주소 값을 더하는 것은 쓸모가 없음 )

② 포인터끼리 뺄 수 있다. ( 주소 값의 거리를 구함으로써 메모리상에서 얼마나 떨어져 있는지 구해낼 수 있음 )

③ 포인터에 정수를 더하거나 뺄 수 있다.

④ 자료형 포인터의 값을 1 증가시키면 자료형의 크기만큼 증가된다.

⑤ 포인터끼리 대입은 가능하다. ( 단, 대입받을 포인터와 대입할 포인터의 타입이 일치해야함 )

⑥ 포인터에 정수를 대입할 수 없다.

⑦ 포인터와 실수와의 연산은 할 수 없다.

⑧ 포인터끼리 비교는 가능하다.

 

- 포인터 증감 연산

     ※ 증감 연산자(++, --)와 참조 연산자(*)는 함께 쓰일 수 있다.

 

 a = *ptr++ a에 ptr의 값을 대입한 후 ptr 증가 (주소가 증가)
 a = (*ptr)++ a에 ptr의 값을 대입한 후 *ptr 증가 (값이 증가)
 a = *++ptr ptr 증가한 후 a에 대입 (주소가 증가, 증가한 주소가 가리키는 값 대입)
 a = ++*ptr *ptr 증가한 후 a에 대입 (값의 증가, 증가한 값 대입)

- ex) a의 주소는 100번지, b의 주소는 200번지라고 가정하자.

 

int b = 10;
int* ptr = &b;
int a;

cout << ptr; // b의 주소값인 200이 출력됨
cout << *ptr; // b의 값인 10이 출력됨

a = *ptr++;

cout << a; // 값을 대입 후 ptr이 증가하므로 10이 출력됨
cout << ptr; // b의 주소에서 4바이트 증가한 204가 출력됨
cout << *ptr; // a의 주소값인 100이 출력됨
int b = 10;
int* ptr = &b;
int a;

cout << ptr; // b의 주소값인 200이 출력됨
cout << *ptr; // b의 값인 10이 출력됨

a = (*ptr)++;

cout << a; // 값을 대입 후 ptr이 증가하므로 10이 출력됨
cout << ptr; // ptr은 증가하지 않으므로 200이 출력됨
cout << *ptr; // ptr의 값이 증가하므로 11이 출력됨
int b = 10;
int* ptr = &b;
int a;

cout << ptr; // b의 주소값인 200이 출력됨
cout << *ptr; // b의 값인 10이 출력됨

a = *++ptr;

cout << a; // ptr을 증가시킨 후 대입하므로 a의 주소값인 
                  100이 출력됨
cout << ptr; // b의 주소에서 4바이트 증가한 204가 출력됨
cout << *ptr; // a의 주소값인 100이 출력됨
int b = 10;
int* ptr = &b;
int a;

cout << ptr; // b의 주소값인 200이 출력됨
cout << *ptr; // b의 값인 10이 출력됨

a = ++*ptr;

cout << a; // ptr의 값을 증가시킨 후 대입하므로 a의 값인
                 11이 출력됨
cout << ptr; // ptr은 증가하지 않으므로 200이 출력됨
cout << *ptr; // ptr의 값이 증가하므로 11이 출력됨

 

▶ 포인터와 배열

- 포인터와 배열은 매우 긴밀한 관게를 갖고 있고, 어떤 부분에서는 서로를 대체할 수도 있다.

- 배열의 이름은 포인터 상수이다.

※ 포인터 상수란 포인터 변수가 가리키고 있는 주소 값을 변경할 수 없는 포인터를 의미

- 가변 문자열 길이를 저장할 때는 배열보다 포인터가 유용하다.

- 정수형 배열의 메모리 할당

ex) int aa[3] = {10, 20, 30};

- 배열의 주소 표현
• aa[0]의 주소(&aa[0]) = 1031번지
• aa[1]의 주소(&aa[1]) = 1035번지
• aa[2]의 주소(&aa[2]) = 1039번지
• 배열 이름 aa = 전체 배열의 주소 = 1031번지
• 배열 aa의 주소를 구할 때는 ‘&’를 쓰지 않고, 단순히 ‘aa’로 표현

- 배열 이름 활용법

ex) aa 값을 1031로 가정하고, aa+1을 계산한 결과는?
    • 예상결과 : aa+1 ➔ 1031 + 1 = 1032 (X)
    • 실제 결과: aa+1 ➔ 1031 + 4 = 1035 (O)

계산 과정)
 ‘+1’의 의미 : 배열 aa의 위치에서 한칸 건너뛰어라
 한칸 : aa가 정수형 배열이므로 4byte
 즉, aa+1 = &aa[1] = 1035

 

배열 첨자로 표현 배열 이름으로 표현 주소
&aa[0] aa + 0 1031
&aa[1] aa + 1 1035
&aa[2] aa + 2 1039

 

 

 

 

'2020-1 STUDY > C++ Study' 카테고리의 다른 글

C++ Study Week 1  (0) 2020.04.12

+ Recent posts