< 포인터 >
▶ 포인터란?
- 변수의 메모리 공간주소를 가리키는 변수
- 포인트 변수의 크기는 무조건 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 |
---|