2009. 1. 5. 20:42
C/C++/MFC
1. 포인터(포인터 변수)의 개념 (1) 일반 변수와 포인터 변수의 차이점 일반 변수는 정수/실수/문자 중 1개의 값을 저장한다. 포인터 변수는 값이 아니라 "주소"(변수, 배열 등 저장공간이 할당된 것)를 저장한다. int i=100, data[100]={ 1, 3, 5, 7, 9 }; int *p, *q; p = &i; // 변수 i의 주소 q = data; // 배열 data의 주소 *p = 200; // i = 200; 과 동일 *(q+1) = 30; // data[1] = 30; 과 동일 (2) 포인터 변수를 이용하여 값을 사용/변경 포인터를 이용하여 값을 사용하거나, 변경할 수 있는 범위는 포인터가 가리키는 주소에 따라 결정된다. 즉, 위 예에서 포인터 p는 i를 가리키므로 1개의 값만 사용/변경할 수 있다. 그러나 q는 배열 data를 가리키므로 100개의 값을 사용/변경할 수 있다. (3) 포인터 변수가 배열을 가리킬 때 --- 포인터 변수의 증감 연산 - 포인터 연산자 '*' 대신에 배열의 인덱스 사용 즉, *(q+3) 은 q[3] 과 동일하며, 배열과 동일한 형태로 사용할 수 있다. - 포인터 변수가 가리키는 배열의 위치 이동 아래와 같이 포인터 변수가 가리키는 위치를 변경할 수 있다. 단, 포인터가 가리키는 배열 data[100]의 인덱스 범위를 벗어날 수 없다. q = q + 2; q++; q--; 2. 포인터 배열 여러 개의 변수(예: 100개의 변수)를 선언하는 대신에 배열을 선언하는 것과 같다. 즉, 포인터 배열은 포인터 변수를 여러 개 선언하는 대신에 포인터 배열을 사용한다. int *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10; 와 같이 10개의 포인터 변수를 선언하기 보다는 int *p[10]; 로 선언하여 p1, p2, ..., p10 대신에 p[0], p[1], ..., p[9] 를 사용한다. 3. 다중 포인터 1차원 포인터는 값(정수/실수/문자)이 저장된 변수(또는 배열)의 주소. 2차원 포인터는 1차원 포인터 변수의 주소. 3차원 포인터는 2차원 포인터 변수의 주소. n차원 포인터는 n-1차원 포인터 변수의 주소. int i=100, data[100]={ 1, 3, 5, 7, 9 }; int *p, *q[10]; // 1차원 포인터 int **dp1, **dp2; // 2차원 포인터 int ***tp1, ***tp2; // 3차원 포인터 p = &i; dp1 = &p; // p는 포인터 변수 tp1 = &dp1; q[2] = data; dp2 = q; // q는 포인터 배열 tp2 = &dp2; 위 예에서 i, *p, **dp1, ***tp1 은 모두 동일하다. 마찬가지로 data[0], *q[2], **dp2, ***tp2 도 동일하다. 4. 포인터와 문자 배열, 스트링 상수의 관계 주의 1. 모든 배열의 이름은 배열에 할당된 공간의 첫번째 "주소"이다. 주의 2. 스트링 상수 "ABC"는 그 자체가 "주소"이며, 값을 변경할 수 없다. ('A', 'B', 'C', '\0' 순서의 4문자가 저장된 "주소"를 지칭한다. 이 문자들은 static area에 자동으로 저장된다.) 단, 문자배열의 초기화(예: char a[] = "ABC";)에 사용된 "ABC"는 문자배열의 초기화를 편리하게 하기 위한 것일 뿐이며, 스트링 상수가 아니다. <예1> char *p; char a[] = { 'A', 'B', 'C', '\0' }; // char a[] = "ABC"; 와 동일함! p = a; *p = 'X'; *(p+1) = 'Y'; *(p+2) = 'Z'; <예2> char *p = "ABC"; // p는 스트링 상수 "ABC"를 가리킴 char b[100]; strcpy(b, p); b[3] = *(p+1); b[4] = 'B'; b[5] = '\0'; 포인터 p는 "스트링 상수"를 가리키고 있으므로 각 문자를 사용할 수 있으나, *p = 'X'; strcpy(p, "XYZ"); 와 같이 값을 변경하는 것은 허용되지 않는다. 그러나 모든 포인터는 다른 주소를 가리키게 할 수 있으므로 p = "XYZ"; p = b; 와 같은 문장은 당연히 허용된다.(포인터의 정확한 이름은 "포인터 변수"이며, 포인터 변수가 다른 주소를 가리키게 할 수 있다.) <예3> char *p = "ABC"; 는 char *p; p = "ABC" 와 같다. 그러나 char a[] = "ABC"; 를 char a[4]; a = "ABC" 와 같이 쓸 수는 없다.(배열이름은 고정된 주소값이며, 포인터 변수가 아니다.) 5. "구조체 변수"와 "구조체 포인터"에서 항목 선택 방법 (1) 연산자 '.' --- "구조체 변수"의 각 항목을 선택할 때(field selection) struct ABC { int a; int b; } x, *p; 의 경우에 "구조체 변수" x의 항목 a 혹은 b를 선택할 때는 x.a = 100; x.b = 200; 과 같이 사용한다. (2) 연산자 '->' --- "구조체 포인터"의 각 항목을 선택할 때(field selection) "구조체 포인터" p를 이용하여 a, b를 가리킬 때는 아래와 같이 사용한다. p = &x; // 포인터 p는 변수 x를 가리키게 했음. p->a = 100; p->b = 200; 위 예에서 p는 포인터이므로 *p는 x와 동일하다. 따라서 일반적인 포인터 사용법에 따라 위 예는 아래와 같이 써도 무방하다. p = &x; (*p).a = 100; (*p).b = 200; 다만, p->a 가 (*p).a 보다 이해하기가 더 편하고 readability가 좋으므로 일반적으로 이렇게 쓰는 경우는 거의 없다. <참고> (*p).a를 *p.a 라고 쓰면 안된다. 왜냐하면 '.'이 '*'보다 우선순위가 높아서 *p.a 는 *(p.a) 와 같아지게 되기 때문이다. 6. 포인터 관련 선언문 예 int *p; --- 포인터 변수 p, 정수형 주소 저장 char *p; --- 포인터 변수 p, 문자형 주소 저장 int *p[n]; --- 크기 n인 포인터 배열 p, (p[0], …, p[n-1]에 정수형 주소 저장) int *p(); --- 함수 p의 선언, "return값이 int pointer"인 함수 p int *p()[]; --- 함수 p의 선언, "return값이 int pointer 배열"인 함수 p int (*p)[n]; --- 포인터 변수 p, "크기 n인 정수형 배열 구조를 갖는 주소"를 저장 int (*p)(); --- 포인터 변수 p, "return값이 int인 함수"의 주소 저장 int (*p[])(); --- 포인터 배열 p, "return값이 int인 함수"의 주소 저장
'C/C++/MFC' 카테고리의 다른 글
API 컨트롤 숨기기, 나타내기 (0) | 2009.01.05 |
---|---|
CWnd 클래스 (0) | 2009.01.05 |
MFC를 사용하여 웹 브라우저 만들기 (0) | 2009.01.02 |
[API]버튼만들기 (0) | 2009.01.02 |
Invalidate() , OnDraw(CDC* pDC) (0) | 2009.01.02 |