1580, 72/79 회원가입  로그인  
   sihun1113
   [C기초] 06 - 포인터의 사용

http://www.hackerschool.org/HS_Boards/zboard.php?id=Free_Lectures&no=1740 [복사]


*----------------------------------------------------------------------------------------------------------*

이 카테고리는 그동안 배웠던것이라던가 공부하면서 알게된 내용들을 중심으로 혹여 참고가 될 수 있을까 싶은 내용들을

모아둔 곳입니다. 따라서 이 글들을 대상이 되는 분들은.. 프로그래밍을 갓 시작했거나 개념이 마구마구 흔들리시는 분들

정도가 되겠습니다. 그러니 너무 욕하지는 말아주세요 =_=;;;



혹시 제가 잘못 알고 있는 부분들이라던가 궁금한 것이 있으면 쪽지 남겨주시거나 리플을 달아주시면 감사하겠습니다.

*----------------------------------------------------------------------------------------------------------*



다시 포인터 본연의 문제로 돌아가죠.



자, 포인터는 '어떠한 주소값을 저장하는 변수'라고 많은 사람들이 이야기 했습니다.

변수는 임의의 값을 저장하고 그것을 조작하기 위해서 사용된다고 우리는 알고 있습니다.

그 말은 주소도 그 값을 저장하고 조작할 수 있을거란 얘기가 되네요. 네 그렇습니다. 주소도 마음대로 조작을 할 수 있습니다. 너무 맘대로 할 수 있다는게 오히려 문제라면 문젤까요?



일반 변수들은 아무리 그 데이터를 지지고 볶고 난리를 쳐도 그 할당된 범위를 벗어나지 않기때문에 별 문제가 되지 않습니다. 하지만 포인터 변수가 가진 데이터는 이런 범위를 제 멋대로 드나들 수 있습니다. 그게...문제인거죠.



그럼 도대체 이 포인터 변수라는 녀석이 하는 역할이 뭔지 알아보도록 합시다.



앞서 메모리는 사물함과 같다고 했습니다. 그리고 변수는 그 사물함을 할당받는 것이라고 했구요. 따라서 사물함을 할당 받았다는 것은 그 고유의 사물함번호를 부여받았다는 것이고, 여기에 자신이 식별하기 쉬운 이름을 달 수 있습니다.



예를들어 0~99번까지 있는 빈 사물함에서 10번이라는 사물함을 개인용도로 부여받았다면 여기에 자기 마음대로 이름을 붙일수도 있겠지요. 예를 들어 '철수꺼'라고..

그러면 나중에 '철수꺼' 사물함에 든 물건을 꺼내라라고 하면 철수꺼라는 이름을 가진 사물함을 찾아서 그곳에 든 내용물을 꺼내면 되겠지요. 이때의 이 '철수꺼'라는 이름은 사물함을 관리하는 사람에게 있어서 10이라는 숫자와 똑같다고 인식될수도 있습니다.

(참고로 변수명은 코딩시의 편의를 위한 수단 일 뿐 컴퓨터는 이를 인식하지 못합니다. 컴파일 과정에서 모든 변수명은 내부적으로는 일련의 숫자주소로 치환됩니다.)



자, 우리는 사물함 번호가 사물함의 주소이고, 이것이 변수의 주소와 동일한 역할을 한다고 이해 했습니다.



이제 만약 3번 사물함을 할당 받을 때 다른 사물함의 번호를 적어두는 용도로 할당을 받았다고 한다면 이것이 바로 포인터의 역할을 하는 것 입니다. 이 사물함은 그저 사물함 번호를 읽는 것만으로는 의미가 없지요. 이 번호가 가리키는 곳을 열어야만 의미가 있습니다.



이 3번 사물함에 10번 사물함 번호를 적어두었다고 생각해 봅시다. 그러면 나는 3번 사물함을 열어 그 안에 적혀 있는 '10'이라는 숫자를 보고 10번 사물함을 열어야 한다는 것을 알 수 있습니다. 그제서야 비로소 10번 사물함의 물건을 넣고 빼고 할 수 있습니다. 이 과정을 '참조'라고 합니다. 그리고 이 '참조'의 역할을 하는 것이 바로 포인터 연산자 '*'입니다.



요 앞의 스터디에서 제가 선언형식을 언급할 때 [char  *pChar;]형식보다는 [char*  pChar;]형식을 추천한다고 말씀드린 바 있습니다. 이때 [*pChar]에서  변수명 앞의 '*'연산자의 의미는 '포인터 변수 할당'이라는 의미를 갖게되고 실제 사용에서는 '포인터 변수 주소 참조'라는 의미를 갖게 되어 의미의 혼동을 주기에 충분합니다. 그러나 만약 후자처럼 데이터 타입 자체가 char*  로 '포인터변수형' 이라는 의미를 갖게 되면 실제 사용부분에 있어서 변수명과 결합된 '*'연산자의 혼동을 그만큼 줄일 수 있습니다. 이 외에도 함수 원형선언시나 강제 형변환등을 해야할때 (char*), (int*), (double*) 형태로 사용되기 때문에 이렇게 익혀두시는 것이 훨씬 도움이 됩니다.



포인터 변수는 [*변수명] 이라는 코드를 통해 참조되는 값에 접근 할 수있습니다.

이게 무슨 말이냐... 다음 설명을 보시죠.



3번 사물함에 10번이라는 사물함 번호를 적어두었다고 했습니다. 그렇다면 3번 사물함의 내용물은 무엇입니까? 단순히 '10'이라는 숫자만이 적혀 있습니다.

따라서,



temp = 3번사물함;



이라는 식을 사용하게 된다면 temp 라는 변수가 갖는 내용은 '10'이라는 숫자입니다. 우리가 원하는 10번 사물함의 내용물이 아니지요.

아래 예제를 보시죠



*-------------------------------------------------------------------------------*

    int    tmp1,tmp2;
    int*  pt;



    tmp1 = 77;               // tmp1변수에 아무값이나 대입한다.

    pt     = &tmp1          // 포인터변수 pt에 tmp1 변수의 주소를 저장한다.

    tmp2 = (int)pt;        // tmp2변수에 pt에 저장 된 값을 저장한다.(동일한 데이터 타입이

                                // 아니기 때문에 에러를 방지하기 위해 강제 형변환을 시켰다)



    printf( "tmp1의 주소    : %d\n", &tmp1 );

    printf( "tmp1의 값       : %d\n",   tmp1 );
    printf( "\n" );

    printf( "pt의 주소        : %d\n", &pt );
    printf( "pt의 값           : %d\n",   pt );
    printf( "pt의 참조값     : %d\n", *pt );
    printf( "\n" );

    printf( "tmp2의 주소    : %d\n", &tmp2 );

    printf( "tmp2의 값       : %d\n",   tmp2 );

    printf( "tmp2의 참조값 : %d\n", *(int*)tmp2 );    // 이런식으로도 쓸 수 있다

*-------------------------------------------------------------------------------*

결과

tmp1의 주소    : 1245052              (제 PC에서의 결과입니다. 실행시마다 달라짐)

tmp1의 값       : 77



pt의 주소        : 1245044

pt의 값           : 1245052

pt의 참조값     : 77



tmp2의 주소    : 1245048

tmp2의 값       : 1245052

tmp2의 참조값 : 77

*-------------------------------------------------------------------------------*



먼저 tmp1의 주소를 주목해 주시구요, pt의 값을 주목해 주십시오. 포인터 변수가 갖는 값은 어디까지나 '주소라는 정수'일 뿐입니다. 즉, 어디까지나 변수에 지나지 않습니다. 다만 형이 다를 뿐이지. 그리고 '*'라는 연산자가 하는 역할은 포인터변수에만 국한되는 것이 아니라 맨 마지막 줄, 즉, tmp2의 참조값이라고 적혀 있는 곳에서처럼 정수를 주소로 사용할 수도 있다는 것 입니다.(물론 형 변환이 필요합니다. 마찬가지로 형이 다르기 때문에)



자, 그럼 뭐가 그리 사람 속을 썩이느냐? 위의 소스코드에서 tmp2의 참조값이라는 내용을 통해 정수를 포인터 변수처럼 사용 할 수 있다는 것을 알았죠? 문제는 이 포인터변수가.. 허용되지 않은 메모리 주소를 참조했을 때 일어납니다.

즉, 우리가 할당받은 메모리 주소는 0~16까지인데 100번지의 메모리를 참조하려고 하면 어떻게 될까요? 우리가 원하는 값이 나오지도 않을 뿐더러 컴파일러는 '허용되지 않은 메모리를 참조하려고 합니다'라며 에러를 띄웁니다.



따라서, 포인터 변수를 사용할때의 주의사항은.. 반드시 할당받은 주소를 사용 할 수 있도록 '할당 된 변수의 주소만 사용해야한다'라는 것 입니다.





다음에는 포인터의 사용상의 특징과 왜 여러가지의 포인터 형을 갖을까..에 대해 알아보겠습니다.

긴 글 읽으시느라 수고 많으셨습니다.

  Hit : 5394     Date : 2011/05/01 11:27



    
160   질문3[5]     sibu02003
05/10 5394
  [C기초] 06 - 포인터의 사용     sihun1113
05/01 5393
158   int 와 unsigned int 에서...[4]     hipro
12/04 5370
157   [C기초] 04 - 포인터에 대한 오해 [1]     sihun1113
05/01 5351
156   [자작] 초보 리버싱 ! [4][2]     siosio24
08/17 5345
155   [자작글]우분투용 그림판을 깔아보자!!!     한승재
03/01 5335
154   [퍼온글] 해킹 공부법     한승재
03/30 5335
153   컴파일러 종류중..[6]     kevin997741
07/18 5315
152   OSI Reference 7 Layers[2]     Mach
04/17 5308
151   리버스엔지니어링 잘하시는분..?     pcw0629
08/26 5297
150   스크립트 알려주실분~1     lcd7132
04/29 5278
149   [자작글]C언어 변수항에 대하여 알아보자!(풀이포함)     한승재
12/26 5275
148   [자작글] 아스키 코드에 대하여 알아보자!     한승재
01/06 5247
147   IT분야로 진로고민이나,취업,이직고민으로 궁금한점들이 많으시죠~?     koreais0
08/08 5240
146   관리자님 있긴 한가요??[1]     rabbitlycat
04/30 5229
145   관련 정보도 어디서 얻을 수 있는지?[1]     39ghwjd
09/12 5208
144   우분투 파티션 설정 방법입니다.[1]     libera826
12/25 5204
143   ㅇㅅㅈ?     rabbitlycat
05/08 5196
142   html와python강의[2]     hktaehyung
05/13 5191
141   레벨업!2     lcd7132
04/27 5157
[1]..[71] 72 [73][74][75][76][77][78][79]

Copyright 1999-2023 Zeroboard / skin by Hackerschool.org / Secure Patch by Hackerschool.org & Wowhacker.com