|
http://www.hackerschool.org/HS_Boards/zboard.php?AllArticle=true&no=1739 [복사]
*----------------------------------------------------------------------------------------------------------*
이 카테고리는 그동안 배웠던것이라던가 공부하면서 알게된 내용들을 중심으로 혹여 참고가 될 수 있을까 싶은 내용들을
모아둔 곳입니다. 따라서 이 글들을 대상이 되는 분들은.. 프로그래밍을 갓 시작했거나 개념이 마구마구 흔들리시는 분들
정도가 되겠습니다. 그러니 너무 욕하지는 말아주세요 =_=;;;
혹시 제가 잘못 알고 있는 부분들이라던가 궁금한 것이 있으면 쪽지 남겨주시거나 리플을 달아주시면 감사하겠습니다.
*----------------------------------------------------------------------------------------------------------*
이 글엔 제가 앞에 써 둔 [02 - 변수의 이해, 03 - 메모리, 변수]와 일부 연결되는 내용이 있습니다. 대부분 무리는 없겠지만 혹시 '이게 뭔소리야'라고 생각되는 부분이 있다면 앞 글을 참조해 주세요.
어느책이나 보면 다 한결같이 '포인터는 다른 변수의 주소를 저장하는 변수이다'라고 설명되어져 있습니다. 지금이야 뭐 이걸 보면 '진짜 웃긴다'라고 생각될정도로 간단한 내용이지만 어디 대부분의 사람들이 그렇겠습니까?
어쨌건 저 문장에서 우리는 포인터도 변수라는 키워드를 얻었습니다. 그렇다면 이 녀석도 앞서 [02 - 변수의 이해]에서 살펴봤던 것 처럼 변수의 3요소를 가지고 있겠네요.
자 그럼 포인터 변수가 가진 요소를 봅시다.
첫번째, 주소
포인터 역시 변수이기 때문에 선언을 하게되면 메모리를 할당받게 됩니다. 그 주소를 가지고 있겠지요? 이 주소가 '포인터'라는 사물함의 고유번호입니다.
두번째, 내용물
이 녀석도 어떻게 보면 일종의 정수형 변수입니다. 0x000...000번지부터 0x????...??번지(메모리의 용량에따라 다르겠죠)까지의 '주소'라는 정수를 저장하는 녀석입니다. 다음에 살펴보겠지만 이 녀석은 약간은 특징이 있는 녀석이다보니 지금은 '주소'라는 걸 저장하는 녀석이구정도만 기억해두세요
세번째, 크기
음.. 이건 쉽게 기억하실 수 있을겁니다. 이녀석의 크기는 무조건 int형의 크기와 동일합니다. 따라서 현재는 4Byte입니다.
int의 크기는 OS의 처리 bit수, 메모리의 용량과 밀접한 관계가 있는데, 현재 정수형 데이터를 저장하기 위해 할당된 4Byte입니다. 왜 현재냐? 지금 보편적으로 사용되고있는 윈도우즈 9x, 2k, NT, XP등은 32bit OS입니다.(물론 64bit 전용 XP가 나오기도 했지만 범용성은 떨어지죠)
과거 16bit OS 시절까지만해도 int의 크기는 2Byte(16bit)였고 8bit OS 시절엔 1Byte였습니다. 감이 팍 오죠?
그렇습니다. 다른 데이터형과는 달리 int는 OS가 데이터를 처리하는데 사용하는 가장 보편적인 단위를 취합니다. 다른 데이터 변환 없이 처리 할 수 있는 가장 빠른 단위를 가장 빈번하게 사용되는 정수연산에 사용하기 위해서이지요.
바꿔말하면 OS는 내부적으로 int단위의 데이터를 전송하며 처리하기 때문에 메모리의 주소 또한 이 범위를 벗어나지 않도록 제한을 두었습니다. 때문에 주소값 역시 int 크기이면 충분하므로 포인터 변수의 크기 또한 int형을 취합니다. 만약 OS가 64bit로 보편화 된다면 포인터 변수의 크기도 64bit로 올라갈 가능성이 높지요. 어쨌거나 지금은 4Byte입니다.
주의하실 점은 포인터는 어떠한 데이터형과도 결합이 되는데 그 모양도 [char*]는 물론이고 심지어 크기가 수십KB에 달하는 대형 클래스라 할지라도 [class명*]의 형태로 사용이 되어집니다. 하지만 어떠한 데이터 포멧이라 하더라도 포인터는 오로지 int 크기만을 취합니다.
char* 라고 1Byte이고 double* 이라고해서 8Byte가 아니란 얘기입니다.
*--------------------------------------------------------------------------------------------------------------------*
포인터의 크기 내용에서 [에이스]님이 틀린 부분을 지적해 주셔서 수정합니다.
포인터의 크기는 OS의 데이터 버스와 상관 없이 CPU가 처리하는 메모리 어드레스 버스의 크기에 따라 결정이 된다고 합니다.
(물론 OS가 최적의 성능을 구현하기 위해 최대한의 메모리 버스를 사용할 것이기에 CPU 처리 bit = OS 처리 bit 가 되겠지만요...)
즉, 16bit 프로세서인 80286급의 CPU에서는 포인터의 크기가 2byte였고, 32bit 프로세서인 펜티엄급의 CPU에서 4byte가 되었다고 합니다. 현재 64bit 프로세서 체제에서 8Byte 포인터가 사용되고 있는지는 확인을 해보지 않아서 잘 모르겠네요.
차후에 컴과 OS를 업그레이드 하면 확인해서 알려드리도록 할게요;;;
정보 주신 [에이스]님 감사드립니다.
*--------------------------------------------------------------------------------------------------------------------*
다음으로 포인터의 사용상의 특징입니다.
일단 포인터라는 다음과 같은 형식으로 선언되고 사용되는 것이 일반적입니다.
int iNum=0;
int *piNum;
piNum = &iNum;
*piNum = 어쩌구저쩌구~~#ㅃ$#!;
이런 형태 처음 포인터를 배울때 본 기억이 있으실겁니다.
처음에는 int형 변수 하나를 선언했습니다. 그 밑줄에는 int형 포인터변수 하나를 선언했지요?
그리고 그 밑줄에선 &연산자를 이용해 iNum의 주소를 얻어서 piNum이라는 포인터 변수에 저장을 하라고 되어 있습니다.
적어도 제가 봤던 책들중 십중팔구는 이런 식으로 코딩이 되어있습니다. 심지어는 대학에서 강의 교재로 사용하는 책에조차 이런 식으로 표기가 되어 있습니다. 하지만 저는 이 선언방식은 처음 배우는 사용자들에게는 맞지 않다고 생각됩니다.
[ int *piNum; ] 이놈때문인데요, 코드 상의 오류는 없습니다. 하지만 우리가 비쥬얼 C나 볼랜드 C, 터보C 등 편집 툴을 사용하는 이유가 무엇이겠습니까? 어차피 똑같은 프로그램을 작성할 거라면 어샘블리어를 써서 기계어를 코딩하면 훨씬 빠르고 강력한 프로그램을 만들 수 있을텐데 말이지요.. 그 이유는 바로 우리같은 코더들이 '알아보기 쉽고 편리하게' 코딩을 하기 위해서입니다.
그렇다면 도대체 뭐가 안좋은가? 자, 여기 2가지 선언 형이 있습니다.
int *ipNum;
int* ipNum;
이 선언식은 완전히 똑같은 의미지만 코드만 약간 다릅니다.
이외에 [int * ipNum]도 동일한 뜻이나 코더들 사이에선 쓰이지 않으니 배제 하겠습니다.
단도직입적으로 말하자면 구별이 쉬운가라는 문제입니다.
저만 그랬는지는 모르겠습니다만, 처음 아무것도 모를 때는 *ipNum 이라는 자체가 변수로서 의미를 갖는 줄 알았습니다. 어떻게 말하면 맞는말이기도 하지만 까놓고 말해서 '완전 틀린답'이지요.
후에 알고보니 ipNum만이 포인터변수의 변수명이고 앞에 붙은 *연산자는 포인터 연산자라고 해서 ipNum이라는 변수가 가진 '주소데이터'의 주소로 찾아가서 거기에 있는 데이터를 조작하라고 하는 의미였던거지요.
int *ipNum과 int* ipNum... 얼핏보면 사실 차이를 느낄 수 없습니다. 하지만 여러가지 다른 변수선언문과 섞어놓으면 확연히 차이가 납니다.
int iNumber;
int *pDstNum;
int *pSrcNum;
char cStr[255];
LPSTR str;
: :
: :
이중에 포인터 변수는 두종류가 있습니다.
첫번째는 int * 형변수인 pDstNum과 pSrcNum이고, 두번째는 LPSTR형 변수인 str입니다.
둘 다 포인터변수이지만 한부류는 *연산자가 붙어있고 하나는 없습니다. 여기서부터 뭔가 일관성이 깨지기 시작하지요. 일관성이 깨진다는 것은 그만큼 복잡해진다는 얘기입니다.
iNumber와 pDstNum을 보면 둘다 데이터타입이 int 형으로 붙어있지만 pDstNum 앞에 붙어있는 *연산자를 보고나서 똑같은 int가 아님을 알 수 있습니다.
하지만 다음 선언문을 보시죠.
int iNumber;
int* pDstNum;
int* pSrcNum;
char cStr[255];
LPSTR str;
: :
: :
일단 변수들 자체에 대해서는 '아 이건 무슨 데이터타입이다'라는 것이 한눈에 들어옵니다.
딱 보기에도 바로 iNumber는 int 형, pDstNum은 int* 형 이라는 것을 구분 할 수 있습니다.
어쩌면 전자가 MSDEV에서 처리되는 형태가 맞을지도 모릅니다. 그건 어떻게 확인을 할 수 있느냐면
int Num1, Num2, Num3, Num4, Num5, ....
등과 같이 ','로 연속해서 선언하는 선언문을 사용할때 *를 어떻게 사용하느냐를 확인해보면 알 수 있지요.
int Num1, *Num2, Num3, *Num4;
라고 선언을 하면 int형 변수 Num1, Nu3과 Int형 포인터 변수 Num2, Num4가 할당됩니다. 반면
int* Num1, Num2, Num3;
라고 선언을 하면 int형 포인터 변수 3개가 할당되는 것이 아닌 Num1만 int형 포인터이고 나머지는 int형으로 선언이 됩니다. 따라서 어떤 의미에서 보면 전자쪽의 의미가 맞는 것 처럼 보이는 것이지요.
하지만 제 개인적으로는 후자쪽으로도 선언식이 정의 될 수 있게 되어야 포인터도 진정한 하나의 데이터 타입으로서 선언 될 수 있을거라고 생각됩니다.
엄연히 int와 int*는 다른 데이터 타입이니까요.
정리합니다.
첫째, 포인터 변수라는 녀석도 어디까지나 변수의 한 종류입니다.
둘째, 따라서 변수가 갖는 3가지 요소인 주소, 내용물, 크기를 동일하게 갖고 있습니다.
세째, 포인터 변수는 무엇에 대한 포인터냐에 관계 없이 항상 int의 크기만을 갖습니다.
네째, 포인터 변수는 다른 변수들이 가진 고유의 주소값만을 저장하기 위한 변수입니다.
다섯째, 포인터 변수도 주소를 갖고 있으므로 이 주소를 저장하는 포인터 변수도 있습니다.
여섯째, 포인터는 char *pChar; 형식이나 char* pChar; 형식으로 선언 할 수 있습니다.(어디까지나 코딩 스타일이니 취향대로 선택하면 되지만 저는 후자의 형식을 사용합니다.)
|
Hit : 7963 Date : 2011/05/01 11:26
|