유돌이

calendar

1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

Notice

'포인터'에 해당되는 글 2

  1. 2009.01.05 포인터 사용법
  2. 2008.12.30 const 사용법
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
posted by 유돌이
2008. 12. 30. 23:12 C/C++/MFC
const에 대해 정리해봤습니다. 약간 불명확한 부분이 있을수도 있겠네요.

const는 변수, 포인터형, 참조형, 함수, 클레스 등에 붙을수 있음.

1. 변수
예)
    const i = 100;
i 값 변경불가

2. 포인터형 : 기본적으로 2가지 형태가 있을 수 있음. 그외 여려형태가 가능
예1) 값은 변경 불가능하지만 주소는 변경가능한 형태
    int temp = 100, temp2 = 200;
    const int *ipConst = &temp;  // *ipConst 값 변경 불가, ipConst(주소)값은 변경가능
    // int const *ipConst = &temp;  // 이런형태로 써도 위와 같은 의미

    // *ipConst = 300;   // 불가능한 형태
    ipConst = &temp2;  // 가능한 형태

예2) 주소는 변경 불가능하지만 값은 변경가능한 형태
    int temp = 100, temp2 = 200;
    int * const iConstp = &temp;  // *iConstp 값 변경 가능, iConstp(주소)값은 변경불가

    *iConstp = 300;   // 가능한 형태
    //iConstp = &temp2;  // 불가능한 형태

주의 : const가 결합되는 위치가 값인지 주소인지에 유의


3. 참조형
예1) 직접적으로 값과 주소 모두 변경 불가능하지만 참조 원본을 통한 값변경은 가능한 경우
   int temp3 = 100, temp5 = 200;
   int const &ircVal = temp3;  
  
   //ircVal = 2000; // 컴파일 에러 발생 (const 참조는 값 변경불가)
   //ircVal = temp5;  // 주소도  변경불가
   temp3 = 9000;  // 참조 원본은 변경가능, 결과적으로 ircVal의 값도 변하게됨
    

예2) 직접적으로 값과 주소 모두 변경 가능하지만 참조가 가르키는 값은 변화가 없는경우
    int temp4 = 300, temp5 = 500;
    int & const icrVal = temp4;

    icrVal = 6000;  // 값변경 가능, 하지만 값에 변경이 안됨  
    cout << " icrVal " << icrVal << endl;  // 여전히 300이 찍힘
    icrVal = temp5; // 주소도 변경가능 역시 값에 변경이 안됨
    cout << " icrVal " << icrVal << endl;  // 여전히 300이 찍힘

4. 함수 : class의 멤버함수인 경우만 const 함수 사용가능. 해당 class의 멤버변수를 변경할수 없음.
예)
class ConstTest
{
public:
        int m_iA;

        ConstTest()
        {        m_iA = 1;           }
        int const_func1( int &a_iA,  int &a_iB) const
        {
                int a = 1;
                int b = 2;
                int c = 0;

                c = a + b;
                a_iA += 100;  
                // m_iA += 100; // 에러발생. 멤버변수는 변경 불가  
                return m_iA;
        }
};
                

5. 클레스
예)
  const CMyConstClass CC;  
  
  // 내부 멤버변수 전체를 변경불가능한 클레스,(생성자 함수만은 예외)
  // 모든 내부 멤버 함수는 기본적으로 const 함수가 되야만함.
  // 내부 함수의 지역 변수및 인자로 받은 변수는 변경가능.

'C/C++/MFC' 카테고리의 다른 글

MFC (디바이스 컨텍스트와 관련 클래스)  (0) 2008.12.30
윈도우즈와 메시지  (0) 2008.12.30
API 기초??  (0) 2008.12.30
C프로그래밍 별모양~  (0) 2008.12.30
BHO 란?  (0) 2008.12.30
posted by 유돌이
prev 1 next