<p><span style="color: #404040; font-family: 굴림;">C Language를 공부하면서 가장 이해하기 어려운 것이 무어냐고 물어본다면,&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">아마도 거의 대부분 "바로 포인터(Pointer)라는 녀석이다!" 라고 말할 것입니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">C에서 다른 건 다 이해가 되어도 "포인터 만큼은 죽어도 모르겠다" 라고 말하는 경우를 제 주변에서도 심심치 않게 봐왔습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">사실 C는 어려울 수밖에 없습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">C를 그저 프로그래밍의 기초 과정에서 배우는 옛날 언어라고 생각하고 가볍게 볼만큼 만만한 녀석이 전혀 아닙니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">C는 어셈블리(Assembly)의 사촌입니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">다시 말하면, C는 하드웨어 - 특히 마이크로프로세서(CPU)와 친한 녀석입니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">때문에 하드웨어에 대한 기반 지식없이는 C를 제대로 이해할 수가 없습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">포인터라는 녀석이 특히 그렇습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">C를 강력하게 만드는 무기가 바로 포인터라고 흔히 말하지만,&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이걸 이해하는 것은 왜 그리 어려운 걸까요.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">조엘('조엘 온 소프트웨어'의 저자)은 이 '포인터'의 개념을 이해하는 게 '그냥 불가능'한 인간이 있다고 말합니다만, 저는 절대로 이해 불가능한 것이 아니라고 굳게 믿습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">제가 여기서 그것을 감히 증명해 보려고 합니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">일단 기초의 기초부터 들어갑니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">아주 유치할 정도로 기초부터 다시 설명하겠습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">1. 메모리(Memory)와 어드레스(Address)&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">일단 포인터의 동작은 전부 메모리(Memory)와 관련이 있습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">따라서 우리는 먼저 메모리에 대해서 알아야 합니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">폰 노이만 구조(프로그램 내장 방식)를 따르는 현대의 모든 컴퓨터들은 기본적으로 모든 것이 주기억장치 - '메모리'에 올라가야 CPU가 실행을 시킬 수 있습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">프로그램 수행 코드도 메모리에 올라가고, 그에 필요한 데이터 역시 메모리에 올라갑니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">일단 여기서 우리는 '데이터'에 관심을 가져보기로 합니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">'100' 이라는 숫자가 메모리에 올려졌다고 해보죠.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">그러면 메모리의 어딘가에 이런식으로 데이터가 저장이 될겁니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">─┬───┬───┬───┬─&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">…│１００│　　　│　　　│…&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">─┴───┴───┴───┴─&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이제 메모리에 저장된 '100'이란 숫자를 꺼내오려고(읽어오려고) 합니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">그런데 문제는 이 100이란 숫자가 드넓은 메모리 영역의 어디에 존재하는지 알아야 한다는 겁니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">그래서 데이터가 저장되는 메모리 공간에는 일종의 일련번호가 부여되어 있습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">그것을 메모리의 주소 - 어드레스(Address)라고 부릅니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">메모리는 기본적으로 바이트(Byte = 8bit) 단위로 데이터가 저장되기 때문에,&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">하나의 어드레스는 메모리 상의 하나의 바이트 공간과 대응됩니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이 말이 이해가 안된다면, C에서의 배열(Array)을 연상하면 되겠습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">int A[10];&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이렇게 하면 C에서는 10개의 정수(int) 데이터를 저장하는 배열이 만들어집니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이것은 마치 10개의 int형 변수를 하나로 묶어서 다루는 것과 같습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">배열의 각 공각에 데이터를 기억시키기 위해서는 이렇게 하죠.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">A[0] = 100;&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">A[1] = 200;&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">A[2] = 300;&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">...&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">A[9] = 1000;&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이때 [ ]안에 넣는 숫자, 이것은 곳 배열에서 어느 영역을 지칭하는 '번호'인 셈인데,&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이것을 메모리의 관점으로 바꿔보면...&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">메모리 전체가 하나의 거대한 배열이라고 가정하면,&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이 거대 배열의 각 영역에 접근하기 위한 '번호'가 필하요게 되고,&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">바로 이것이 주소(Address)라는 것으로 보면 됩니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">2. 변수&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">우리가 C 코드를 만들때, main() 함수를 작성하면서 가장 먼저하는 일이 무엇입니까?&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">────────────────────────────────────────&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">void main()&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">{&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">int a, b;&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">...&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">}&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">────────────────────────────────────────&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">바로 변수를 선언하는 거죠.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">바로 이 선언이라는 것은, 자신이 사용할 메모리 공간을 예약하는 것입니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">─┬───┬───┬───┬─&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">…│　ａ　│　ｂ　│　　　│…&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">─┴───┴───┴───┴─&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">그럼 예약도 되었겠다, 값을 써보도록 하죠.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">a = 10;&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">b = 20;&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">─┬───┬───┬───┬─&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">…│　１０│　２０│　　　│…&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">─┴───┴───┴───┴─&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">그럼 이번엔 a, b의 값을 한번 출력해 봅니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">printf("%d %d", a, b);&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">[결과]&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">10 20&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">C에서는 이처럼 변수 이름을 통해서 메모리에 값을 읽고 쓸 수가 있습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">이 당연한 걸 왜 새삼스레 다시 설명하냐고 태클이 들어올 것 같습니다만, 잠시 참아주세요.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">앞서 메모리 상의 데이터는 '어드레스'를 통해서 접근할 수 있다고 얘기했습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">C에서 변수는 메모리의 한 부분입니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">그런데 C에서는 '변수 이름'을 가지고 접근하고 있군요.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">바로 이 '변수 이름'이라는 것은 메모리 어드레스를 추상화시킨 것입니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">실제 C에서는 변수앞에 '&amp;' 연산자를 붙여서 그 변수의 어드레스를 바로 얻을 수 있습니다.&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">────────────────────────────────────────&nbsp;</span><br style="color: #404040; font-family: 굴림;" /><span style="color: #404040; font-family: 굴림;">#include&nbsp;</span><stdio.h style="color: #404040; font-family: 굴림;"><br />void main()&nbsp;<br />{&nbsp;<br />int a, b;&nbsp;<br />a = 10;&nbsp;<br />b = 20;&nbsp;<br />printf("Address: %d %d\n", &amp;a, &amp;b);&nbsp;<br />}&nbsp;<br /><br />[결과]&nbsp;<br /><img name="target_resize_image[]" tmp_width="0" tmp_height="0" src="http://blogfiles10.naver.net/data19/2006/5/6/185/pointer_test_1-bitessay.jpg" style="cursor: pointer;" />&nbsp;<br />────────────────────────────────────────&nbsp;<br />이 결과를 잘 보면, a와 b의 어드레스에는 4만큼의 차이가 있습니다.&nbsp;<br />이것은 둘다 int형(정수형)이고, 일반적으로 32bit CPU에서 정수는 4byte의 크기를 같습니다.&nbsp;<br />그리고 두 변수가 나란히 선언되었기 때문에, 이 둘은 메모리상에서도 연속해서 공간을 차지하게 됩니다.&nbsp;<br />참고로 x86 계열의 CPU는 어드레스가 높은 쪽에서 낮은쪽으로 채워집니다.&nbsp;<br />때문에 먼저 선언된 쪽이 높은 주소값을 가지게 됩니다.&nbsp;<br /><br />3. 데이터와 타입&nbsp;<br />기본상식이지만, 컴퓨터에서는 모든 데이터는 2진수(Binary)로 표현됩니다.&nbsp;<br />이말은 즉, 그 어떤 종류의 데이터라할지라고 메모리에 저장될 때는 2진수로 기록된다고도 할 수 있습니다.&nbsp;<br /><img name="target_resize_image[]" tmp_width="0" tmp_height="0" src="http://blogfiles7.naver.net/data17/2006/5/6/86/binary-bitessay.gif" style="cursor: pointer;" />&nbsp;<br />그럼 반대로, 메모리에 저장된 데이터를 읽어 올때도 역시, 이것을 "문자열"로도 "정수"로도 "실수"로도, 기타 얼마든지 다른 형식으로 읽어 들일 수 있다는 것이 됩니다.&nbsp;<br /><img name="target_resize_image[]" tmp_width="0" tmp_height="0" src="http://blogfiles16.naver.net/data19/2006/5/6/239/binary2-bitessay.gif" style="cursor: pointer;" />&nbsp;<br />그렇다면, 메모리에 저장된 자료를 과연 어떤 형식(Type)으로 해석해야 하는지 문제가 됩니다.&nbsp;<br /><br />그렇기 때문에 우리는 변수를 선언할 때, 반드시 그 변수가 취급하는 데이터형(Type)을 명시하게 됩니다.&nbsp;<br /><br />int number; // 정수형&nbsp;<br />float real_num; // 실수형&nbsp;<br />double bigsize_real; // 큰 실수형&nbsp;<br />char* string; // 문자열&nbsp;<br /><br />또한 이 데이터 타입은, 변수의 선언에 있어서, 그 변수에게 얼마만큼의 메모리 공간을 할당해야 하는가를 결정하는 정보이기도 합니다.&nbsp;<br /><br />보통 int와 float은 4 Byte 크기를 할당받게 되고, double은 8Byte, 문자열의 경우에는 문자열의 길이에 따라 다릅니다.&nbsp;<br /><br />4. 포인터&nbsp;<br />자, 이제 드디어 포인터에 대해 이야기할 차례입니다.&nbsp;<br />"포인터(Pointer)란 무엇인가?"&nbsp;<br />라고 묻는 다면, 그 정의는 간단합니다.&nbsp;<br />"메모리의 어드레스(Address)를 데이터로 취급하는 변수"&nbsp;<br />즉 포인터 변수에는 어드레스 값을 저장할 수 있습니다.&nbsp;<br />그래서 포인터 변수는 다음처럼 특정 변수의 어드레스를 기억하는 것이 가능합니다.&nbsp;<br /><br />int V;&nbsp;<br />int *P;&nbsp;<br />P = &amp;V;&nbsp;<br /><br />포인터 변수가 어느 변수의 주소(Address)값을 가지고 있는 상태.&nbsp;<br />이 상태를 우리는 포인터 변수 P가 일반 변수 V를 "가리키고 있다"라고 표현합니다.&nbsp;<br /><img name="target_resize_image[]" tmp_width="0" tmp_height="0" src="http://blogfiles4.naver.net/data17/2006/5/6/211/pointer_1-bitessay.gif" style="cursor: pointer;" />&nbsp;<br />앞서 메모리의 어드레스를 통해서 메모리에 있는 데이터에 접근할 수 있다고 했습니다.&nbsp;<br />변수 역시 자신이 어드레스를 가지고 있기 때문에, 우리가 변수를 통해서 데이터를 읽고 쓸수 있는 것입니다.&nbsp;<br /><br />그렇다면, 포인터 변수가 데이터로서 가지고 있는 어드레스를 이용해서도 메모리에 접근 할 수 있지 않겠습니까?&nbsp;<br /><img name="target_resize_image[]" tmp_width="0" tmp_height="0" src="http://blogfiles6.naver.net/data17/2006/5/6/197/pointer_2-bitessay.gif" style="cursor: pointer;" />&nbsp;<br />변수 V가 가지고 있는 데이터에 접근 하려 한다고 하면, 보통은 변수 V를 직접 호출해서 바로 접근할 수 있습니다.&nbsp;<br />그런데 포인터 변수 P가 V를 가리키고 있는 상태에서는 포인터 변수 P를 통해서 간접적으로 V에 접근할 수도 있게 됩니다.&nbsp;<br />예를 들면,&nbsp;<br /><br />V = 10;&nbsp;<br /><br />이렇게 V에 10 이란 상수를 바로 기록할 수도 있고,&nbsp;<br /><br />*P = 10;&nbsp;<br /><br />이렇게 포인터 변수를 통해서 간접적으로 V에 10을 저장시킬 수도 있습니다.&nbsp;<br />여기서 포인터 변수 앞에 쓰인 '*' 연산자는 보통 "P가 가리키고 있는 변수의 값을 가져온다" 라고 말하는데, 사실 정확한 정의는 "P가 가리키고 있는 곳=장소" 그 자체입니다.&nbsp;<br /><br />간단히 말하면 '*' 연산자가 붙은 포인터 변수 = (*P) 자체가 하나의 변수처럼 취급될 수 있다는 겁니다.&nbsp;<br />따라서 아래처럼 값을 가져오는데도 쓸 수 있고,&nbsp;<br /><br />A = *P;&nbsp;<br /><br />이처럼 값을 저장할 때도 쓸 수 있습니다.&nbsp;<br /><br />*P = A;&nbsp;<br /><br />5. 포인터와 타입&nbsp;<br />C에서 포인터 변수를 선언은 이런식으로 하게됩니다.&nbsp;<br /><br />int *p;&nbsp;<br /><br />자 그럼, 이 p 라는 변수의 타입(Type)은 무엇일까요? 정수(int) 일까요 ??&nbsp;<br />잠깐 다른 문제를 내보겠습니다.&nbsp;<br /><br />정수형(int) 변수의 타입(Type)은? → 정수(int)&nbsp;<br />실수형(float) 변수의 타입은? → 실수(float)&nbsp;<br /><br />자, 그럼 포인터 변수의 타입은?&nbsp;<br />네, 당연히 포인터(Pointer)입니다.&nbsp;<br /><br />int *ip;&nbsp;<br />float *fp;&nbsp;<br />double *dp;&nbsp;<br />char *cp;&nbsp;<br />void *vp;&nbsp;<br /><br />이렇게 선언된 변수들은 죄다 '포인터' 형입니다.&nbsp;<br />결국 그 정체는 그저 '어드레스'를 저장하는 변수인 겁니다.&nbsp;<br />32bit CPU에서 이 어드레스는 32bit 정수(4 Byte)로 표현됩니다.&nbsp;<br />따라서 결국은 포인터 변수라는 건 int형 변수나 별반 다를게 없습니다.&nbsp;<br />단지 그 정수를 '어드레스'라고 해석할 뿐인 겁니다.&nbsp;<br />C에서는 변수 선언시에, 이름 앞에 '*' 라는 표시를 붙여서 이것이 포인터형 변수라고 컴파일러에게 알려줍니다.&nbsp;<br />그럼 * 앞에 있는 int 같은 타입 정보는 대체 무엇인가?&nbsp;<br /><br />앞서 메모리에 저장된 데이터를 해석하려면 타입(Type) 정보가 필요하다고 했습니다.&nbsp;<br />포인터 변수의 타입은 포인터이니까, 포인터 변수의 데이터는 어드레스로 인식하면 됩니다.&nbsp;<br /><br />그치만, 포인터 변수가 가리키는 곳(포인터 변수에 저장된 어드레스)에 있는 데이터는 어떻게 해석해야 하는가가 문제가 됩니다.&nbsp;<br />따라서 포인터 변수를 선언할 때는 두 가지 타입 정보가 필요합니다.&nbsp;<br />정확히 말하면, 포인터 변수가 가리키는 것에 대한 타입 정보가 추가로 필요해 지는 겁니다.&nbsp;<br /><br />int *p;&nbsp;<br /><br />이렇게 선언된 포인터 변수는 가리키는 대상이 정수(int) 타입이라는 것을 의미합니다.&nbsp;<br />앞서 '*' 가 붙은건 다 포인터형 변수라고 말했습니다만...&nbsp;<br /><br />int *ip;&nbsp;<br />float *fp;&nbsp;<br /><br />그 말대로라면 여기서의 ip와 fp는 같은 타입이라는 얘기가 됩니다.&nbsp;<br />그럼 이런 것도 가능할까요.&nbsp;<br /><br />int a = 10;&nbsp;<br />int *ip;&nbsp;<br />float *fp;&nbsp;<br />ip = &amp;a;&nbsp;<br />fp = ip;&nbsp;<br /><br />마지막 문장 "fp = ip"에서는 ip가 가진 값이 변수 a에 대한 어드레스이므로, fp에는 a의 어드레스 값이 기록됩니다. "fp = &amp;a"와 같은 결과가 되죠.&nbsp;<br />결론적으로 ip와 fp에 둘 다 같은 정수형 변수 a의 어드레스를 저장시켰습니다.&nbsp;<br />뭔가 불안해 보이는 코드이지만, 사실 이렇게 해도 컴파일은 됩니다.&nbsp;<br />다만 컴파일러는 정중하게 경고(warring) 메세지를 보냅니다.&nbsp;<br /><br />'int ' differs in levels of indirection from 'float *'&nbsp;<br /><br />실수형 자료를 가리키는 포인터 fp에 정수형 변수의 어드레스를 할당시켰다는 거지요.&nbsp;<br />그래서 데이터를 잘못 해석해버릴 가능성이 있기 때문에 컴파일러가 경고를 보낸겁니다.&nbsp;<br />실제로 저렇게 사용하면 큰일(?)날 수 있습니다(...)&nbsp;<br /><br />마무리&nbsp;<br />결론적으로 포인터라는 것은 메모리, 그 중에서도 '어드레스'를 다루는 테크닉입니다.&nbsp;<br />그렇기에 포인터를 알려면 메모리와 어드레스에 대한 이해가 필수인 거지요.&nbsp;<br />그래서 본격적으로 포인터에 대해 얘기하기 전에,&nbsp;<br />메모리와 연관지어서 기초적인 부분을 다시 정리해본 겁니다.&nbsp;<br />여기까진 그다지 어렵진 않을 겁니다.&nbsp;<br /><br />다음에는 포인터를 처음 접할때 조금씩 햇갈리기 시작하는 배열과 포인터의 관계에 대해서 알아보겠습니다.</stdio.h></p>