이 부분을 읽으시고 도움이 되시길 바랍니다.
Computer Language 는 A World Convert To B World 형식으로 이루어져 있습니다. World(세상,차원)을 모티브로 Convert 가 되는데요. C.L 에서 디폴트적인 부분(모든 컴퓨터 언어)은 Mathmatics World Convert To Digital World 입니다.
Convert To 시 World간 손실일 일어나는데, A World 를 Source World , B World를 Dest World로 부를 수 있습니다.
즉 Digital World는 기본적으로 Mathmatics(수학 차원)에 변환이 기본적으로 행해진다 할 수 있습니다. Convert 시 World간 손실이 일어나는데 이를 월드간 변환 손실율이라고 부릅니다. 즉 완벽히 A World를 가져올 수 없다는 뜻 입니다.
*ps OOP , CBP 에서는 다양한 A World (Source World)가 있습니다. C++ 이상급 언어공부할 시 참고하시라고 씁니다.
OOP 이상급 World는 Real World(현실)체계에서 특정 부분을 가져옵니다. OOP는 Object를 가져오는대요. Real World에서 Object(객체)가 Convert To Digital World로 변환시 월드간 변환 손실율 때문에 현재 그 어떤 언어, 기법도 완벽히 Real World에 Object를 가져올 수 없지요.
C Language에서는 Mathmatics World 이외에 Real World 부분 중 Machine World를 가져왔습니다. (기계적) 보다 상위적으로 올라가면 이 역시 OOP에 모태를 둔 Object를 두고 있다고 볼 수 있습니다. :)
C언어에서 Value라고 불리는 것은 관점 (Focus)에 따른 부분입니다.
즉 C언어에서 int iValue를 설명하면 Numberic 군에 포함된 Int 타입에 Value라고 표현하지만 C++에서 동일 코드를 읽을 시
Numberic 군에 포함된 int 타입에 '객체'라고 봅니다.
객체가 더 상위개념이며, 기계역시 Real World에 하나의 객체이니 객체에 설명을 빌리겠습니다.
Convert To 때문에 월드간 변환 손실율이 적용되어 있기 때문에 객체(Object)를 완벽히 가져오지 못했습니다만 객체를 표현할 수 있는 기본적인 틀은 가져왔습니다.
Digital World 부분에서 Object 중에서도 C,C++에 적용된 Object(value)는 다음과 같은 기본적인 틀을 가지고 있습니다.
Property + Behaivor (특성 + 행위)에 결합입니다. int iValue를 설명하기 위해 조금더 규격화된 설명을 말하자면
모든 객체는 T.N.V.A를 만족합니다 (C,C++)
T.N.V.A는 Type Name Value Address 입니다.
Type Name Value Address
int iValue Default Value(Garbage Value) Auto(Compiler Auto Allocate)
가 됩니다. 후.. 포인터 설명하기 위해서 :) 돌아가시지 마시라고 아주 간단한 배경지식을 말씀드렸습니다.. ㅜㅜ
자 객체는 T.N.V.A 를 만족한다고 했지요?
Type Name Value Address
int iValue = 10;
int* pValue = &iValue;
위와 같은 코드가 있습니다. 여기에서 초보자 분들은 Pointer를 iValue와 같다고 이야기하거나, 혼용할 수 있는데 전혀 틀린 말입니다.
객체는 T.N.V.A를 만족해야 한다고 했지요? 역으로 말하면 T.N.V.A를 만족하면 '객체'가 된다는 뜻 입니다.
즉 iValue, pValue는 서로 다른 객체입니다.
포인터는 Value를 통해서 Value 에 들어가있는 Address를 통해서 '메모리'에 직접 접근하여 값을 Type을 통해서 해석합니다.
그렇기 때문에 & (Bind)되어 있는 위치가 Un Safe시 (객체가 소멸되는 시점, 혹은 메모리 free 되는 시점)에 대해서 매우 위험하게 접근할 가능성이 있습니다. 그래서 포인터를 쓸 때 바인드 객체가 소멸되었다면 Null로 dangling 시키는 것 입니다.
:) 두 번째 베이스 이론을 끝냈습니다.
이제 본격적으로 포인터가 무엇인지 설명해드리면 공부하시는데 도움이 되실 것 같습니다.
Pointer는 일반적인 시중 책에서 언급한 'Point(가르키다)' 라고 해석하면 절대 안됩니다...
Pointer는 말 그대로 Point(가르키다)라고 해석하는 것이 아닌 Bind(묶는다) 라고 표현해야 합니다.
포인터는 자신의 Value를 = (대입 연산자)를 통해서 물리 메모리 주소를 Bind 시키는대요. 이 때 객체 자체를 Bind 시키는 것이 아닌
Source Object에 첫 번째 Physics Memory Address를 Bind 합니다. P.M.A는 객체가 시작되는 첫번째 메모리 위치를 뜻합니다.
즉!
int iValue = 10;
int pValue = &iValue; // 이 때만 Bind
*pValue = 20; // 이때는 P.M.A를 통해서 직접 접근이기 때문에 iValue와는 전혀 상관없습니다.
즉 Point는 int pValue = &iValue; 시에만 P.M.A를 Bind 시키고 그 뒤로는 자신의 Value를 통해서 P.M.A에 직접 접근하여 값을 컨트롤 합니다.
Low Level Pointer (Assem, Embed) 부분이나 컴파일러 아랫단에서 수행하는 연산처리 이외 고급 프로그래밍 (컴파일러에서 접근하는 기본적인 방법) 에서는 High Level Pointer 로서 격상되며 이 때 Pointer Object에 Type을 통하여 Safe Value를 판정합니다.
(이 부분은 ..아하~ 제가 첨부터 기초를 가르쳐드리면 쭉쭉 말할 수 있지만 ..ㅠㅠ)
Safe Value 판정이 나면 값이 들어가지고 그 이외에 부분에 대해서는 'Fail' 판정을 냅니다.
소스코드에서 쓰시는 Casting은 객체의 Default 적인 Type(해석)부분을 가리고 현재 코드 연산처리에서 Type(해석) 부분을 사용자가 임의로 바꾸는 것을 의미합니다. 그렇기 때문에 Casting 에서 무조건적인 * 부분이 필요한 이유가 이 부분이며 Casting 시 Low Level -> High level 격상에서
Casting Type이 들어가서 해석하게 되는 것 입니다.
void* 는 Low Level -> High Level 부분에 격상 부분에 객체가 해석될 Type이 없기 때문에 무조건적으로 Casting이 필요한 부분이 바로 이 때문이지요.
이런 트릭과 이론을 통해서 객체의 Type을 가려서 다양한 객체를 넣는 방법이 void* 캐스팅입니다.
포인터에 대해서 어려워하시는데. 정리하자면 다음과 같습니다.
Computer Language는 A World Convert To B World 에서 일어나는 World 간 변환 손실율을 가지고 있으며 C,C++역시 크게보면 Real World에서 왔기 때문에 C,C++은 모두 Object로 바라볼 수 있습니다. 다만 둘의 환경에서 동일 코드를 다르게 해석하는 이유는 '관점' Focus 때문이며 이외를 제외하면
객체는 기본적인 '실체화(Instance)'를 이루기 위하여 T.N.V.A 라는 특성을 만족해야 합니다.
int iValue가 객체라는 것을 혼동할 수 있는데 이때 Behaivor(행위)는 다른 용어로는 Function,Property,Method등으로 불립니다.
여기에서 int iValue가 과연 Behaivor를 가지고 있느냐를 궁금해하실 수 있는데, int iValue + int iValue2 같은 + 연산 즉
First Value Opertator Second Value 규약인 IPO를 만족하기 위하여
First Object(First Value, L -Value) 는 Second Value (R-Value)에 대하여 Operator를 수행할 수 있는 것이 미리 정의되어 있어서 가능합니다.
여기에서 Operator (덧셈등)은 Behaivor라고 표현할 수 있습니다.
컴파일러들은 Default Object Type에 대하여 위와 같은 Operator Behaivor를 정의하고 있습니다.
위와 동일한 이유로 structure , class 같은 부분은 자신만에 Behaivor를 만들어줘야하는데. 가장 간단한 Inner Function, 혹은 operator 를 통해서 자체로 통해서 만들 수 있으며 Functor 같은 부분을 만드는 것 입니다.
Pointer는 Default 중에서도 P.M.A를 통해서 직접 접근하는 특수목적 타입이기 때문에 Point(가르키다)라는 개념으로 이해하기 보다는
Bind(묶는다)라고 표현하시면 됩니다. Pointer를 Point(가르키다)라고 표현하면 null 포인터를 설명할 수 없습니다.
null pointer는 말 그대로 null (초기화, Address상 0x0~) 위치에 있으며 이 뜻은 dangling (단절된) pointer 라고 부를 수 있습니다.
즉 Pointer는 대입 연산(=) 시에만 Source Object에 P.M.A를 묶고 그 이외에 부분에 대해서는 P.M.A를 통해서 메모리상 직접 접근하기 때문에
언제나 Source Object 소멸시 (memory Release) null 포인터를 주어서 현재 내 Pointer는 단절되어 있다라고 표현하는 것 입니다.
위에가 왜 문제가 되느냐면 O/S는 프로그램에서 Allocate(할당) 요청이 들어오면 알맞은 위치에 Memory Block 을 통해서 현재 이 메모리 부분은
메모리 사용 중이라고 표시하며 해제시 'Memory Release'를 통해서 해제해주기 때문입니다.
포인터는 Low Level,High Level 같은 부분으로 동작하기 때문에 Default Object(int,float)같은 부분에 대해서 초기화를 보장하지 않습니다.
여기에서 Default Object Initialize 부분은 컴파일러는 지역변수를 선언하면 '자동으로' - '쓰레기값'이라고 불리는 값으로 현재 이 객체는 '사용자가 초기화' 시키지 않는다는 것을 판정하는 것 입니다. Global, Static 경우에는 자동적으로 Zero, Null 을 통해서 초기화를 메커니즘을 수행합니다.
다만 여기에서 주의해야할 점은 Allocate시 Initialize입니다. Release(해제)시 컴파일러는 'Null'이나 '쓰레기값'으로 초기화 시키지 않습니다.
왜냐하면 그 메모리가 다시 OS에서 사용요청을 받을때 Block 시키며 Default Object Initialize를 수행하기 때문입니다.
여기에서 문제는 Pointer에서 Bind 되는 객체가 Release가 되었을 때 OS는 메모리 Release 만 수행하며 값은 아직도 그대로인 경우입니다.
다른 누군가가 그 위치를 Allocate 시키지 않는한 말입니다. 여기에서 강력한 문제는 OS가 다시 그 메모리 부분중 일부분을 Block 시키고 Default Object initiaize , 시킬 때 과연 이 Pointer 객체의 Bind 되어 있는 주소값이 프로그래머가 원하는 ' 그 값'을 가지고 있느냐에서 모호한 부분을 가지고 있기 때문에 책에서는 반드시 Source Object가 소멸시 null를 통해서 안전성을 보장하라는 말 입니다.
이런 트릭을 이용하여 Release 객체의 Function Address를 통해서 객체를 생성하지 않고 이용하는 트릭적인 방법등이 있습니다만..ㅜㅜ
이 부분에 대해서도 제가 기초부터 배웠다면 즐거웠을 터인대..
프로그래머는 기초를 튼튼히 해야합니다.
코드적인 테크닉컬 부분은 다른 분들이 해결해주실거라 믿습니다~
다만 기초적인 부분은 현재 Missing Link가 많이 되어 있기 때문에 제가 이렇게 화장실에서 노트북으로 타자를 치고 있는 것 입니다.........
프로그래머는 기초를 튼튼히 해야합니다.
C,C++언어 기초입문서 책은 국,내외를 비롯하여 99%가 테크닉적인 부분을 가르치고 있습니다. 테크닉적인 부분은 공부하시는분에게 Expert ,Master 같은 기술적인 '능숙도'를 올려줄 뿐, 기초를 튼튼하게 하지 못합니다.
기초는 입문서를 많이 읽느냐가 아니라 올바르고 정확한 부분을 명쾌하게 대답할 수 있는 것이 기초를 탄탄히 했다는 뜻 입니다.
제가 본 최근에 책 중에서는 null 포인터를 왜 써야하며, Convert to 손실, 심지어! [] = * 같고 이 부분이 Mathmatics에서 와서 수식 전환이 된다는 것을 모르는 분이 정말 많더군요.. 꼭! 기초 튼튼히 하셈요!
-Missing Link 문제~
Array [] = * 연산과 같습니다. 이 부분에 대해서는 어느정도 많은 분들이 아시지요.
Computer Language는 A World Convert To B World라고 했습니다.
Mathmatics World가 Default라고 했지요.
int iArray[3] = {1,100,1000};
cout << iArray[1] << endl;
cout << *(iArray+1) << endl;
cout << *(1 +iArray) << endl;
위를 출력해보세요. 여기까지는 '아하..그렇구나' 라고 이해할 수 있습니다만.
cout << 1[iArray] << endl;
이게 출력이 될까요? 안되면 이유는 무엇이고, 출력되면 이유는 무엇입니까?
답은 아래에 있습니다. 즐공하세욤
답은 출력됩니다.
Mathmatics World에서 Default 적인 부분이 무엇이지요?
1 + 2 = 3 이지요? 2 +1 = 3 입니다.
iArray[1] 이 *(iArray +1) 과 같다고 했습니다.
또한 *(1 + iArray)도 똑같은 결과를 출력합니다.
당연히 Mathmatics World 에서 L-Value(First Value), R-Value(Second Value) 위치를 변경해도 동일 결과 값을 표현하는 것과 같습니다.
당연히 Mathmatics World를 포함하고 있는 Computer Language에서 iArray[1] 과 1[iArray]는 같은 말이며
이 부분에 대한 자세한 설명은 위에서 간단히 언급한 A World Convert To B world 와,
Low Level Pointer -> Promotion(승급) -> High Level Pointer 에 이론이 적용되어 있기 때문입니다.. :)
기초를 많이 못가르쳐드려서 죄송합니다. 원래대로라면 쏵다 처음부터 재대로 가르치면 C,C++,Java,C# 언어등은 거기서 거기인대 말이지요..