-
프로그래밍에서 말하는 포인터(pointer)란 다른 변수, 혹은 그 변수의 메모리 공간주소를 가리키는 변수를 말한다.
포인터가 가리키는 값을 가져오는 것을 역참조(逆參照, dereferencing)라고 한다. - Wiki -
포인터의 장점
포인터란 일반 변수와는 달리 메모리 주소를 저장하는 변수를 말한다.
일반적으로 변수는 특정 '값'을 저장하는데 반해 포인터는
특정 '메모리 주소'를 저장하며 저장한 메모리 주소에 저장되어 있는 값을 읽어올 수 있다.
특정 메모리 주소를 저장하고, 주소에 저장된 값을 읽어올 수 있다는 특징 때문에
포인터는 많은 상황에서 아주 유용하게 사용할 수 있다.
메모리상에 연속적으로 저장되어 있는 배열을 조작할 때에도
포인터를 이용하면 편리하다. (엄밀히 말하면 배열도 포인터이다.)
또한 포인터는 저장하는 값의 성질에 따라 크기가 변하는 일반 변수와는 달리
포인터 변수는 타입에 관계없이 항상 4바이트를 유지한다.
크기가 100Kb가 넘는 구조체, 클래스를 가리키는 포인터라 할지라도 포인터 자체 크기는 항상 4바이트이다.그러하기 때문에 함수의 인수로 넘기는 과정에서 일반 변수, 구조체를 쓰는 것 보다는 포인터를 쓰는것이 더욱 효과적이다.
만약 크기가 큰 구조체 배열을 함수의 인수로 넘겨야한다고 하자.
그렇다면 프로그램은 그 함수가 한 번 실행될 때마다 크기만큼 연산속도가 느려질 것이다.
물론 현재에는 하드웨어가 발달해서 이정도는 속도에 영향을 미치지 못한다고 하지만,
만약 서버 프로그램을 제작한다거나 다른 컴퓨터와 네트웤 작업을 하는 프로그램을 제작할 경우
또는 함수의 사용이 매초마다 1번씩 이루어지는 경우라던가 할 때에는 이 작은 크기로 인해서
프로그램의 속도가 급격히 저하될 수 있다.
오류와 속도에 있어서는 예민할 수 밖에 없는 프로그래머의 입장에서 포인터라는 것은 아주 유용한 녀석이 아닐 수 없다.
(현재 공부하고있는 본인의 입장에서도 포인터는 배우고나면 정말 엄청나게 도움이되는 녀석이다.)포인터의 사용
프로그램 실행시 레지스터 변수를 제외한 모든 변수는 메모리에 저장되기 때문에
메모리의 번지를 기억하는 포인터를 항상 선언할 수 있다.
하지만 포인터를 사용하려면 가리키려는 대상체가 존재해야 하며,
대상체의 타입과 포인터의 타입이 일치해야만 한다. (아무것도 없는 메모리를 가리킬 수는 없지 않은가)
포인터와 대상체의 타입이 같아야 하는 이유는. 타입이 서로 같아야 포인터가
* 연산자로 저장되어있는 값을 올바르게 읽을 수 있기 때문이다.
정수와 실수 문자형 구조체 등등 각 타입마다 메모리의 크기가 저장되는 저장되는 방식이 다르기 때문에
포인터는 읽어오려는 메모리 주소가 어떤 크기만큼 어떤 형식으로 구성되어있는지 알 수 있어야 한다.
정수형 포인터라면 가리키는 메모리로부터 4바이트를 읽어오면 맨 처음 비트를 부호비트로 인식하고
나머지 비트를 2진값으로 읽어올 것이다. 그리고 실수형 포인터라면 4바이트를 읽어오면서 첫 비트를 부호비트로,
그 후 8비트를 지수부 비트로, 나머지비트를 가수부 비트로 인식하여 그것을 토대로 실수값을 계산할 것이다.
그러므로 정수형 포인터에 실수 변수를 강제 형변환해서 대입했다고해서
정수형 포인터로 값을 읽어올 때 정수부분만 읽어오는 것이 아니며 아주 엉뚱한 값이 나오게 된다.
(정수형은 부호|값 의 형식으로 저장되지만 실수형은 부호|지수부|가수부 의 형식으로 저장되므로)
서로 연관이 있는 int , short 끼리나, int ,char 와 같은 경우는 사용할 수 있지만
int 와 float 이라던가 float 과 char 등의 타입은 연동할 수 없다.
변수가 저장되는 메모리는 정수, 실수, 문자형 등의 형식이 있는게 아니라 단순한 비트로 구성되어 있으며
각 타입별 변수들이 타입에 맞는 형식으로 읽어오는 것이므로 포인터를 사용하려면 포인터의 타입과
대상체의 타입과 일치하여야 한다.
또한 포인터가 배열을 가리키고 있을 경우 앞뒤로 메모리 번지를 이동해야할 때에도 가리키고 있는 대상체 타입의
크기만큼 이동해야 하므로 포인터는 자신이 가리키고 있는 대상체의 타입에 대한 정보를 가지고 있어야 한다.
(ptr++ 는 ptr + (sizeof(타입)) 과 같다. )
포인터 사용의 규칙
포인터끼리는 더할 수 없다.
포인터가 가리키는 메모리 번지는 일반적인 숫자와 달리 크기를 비교하는 대상이 아니기 때문에
포인터끼리 더한다고해서 의미있는 값이 나오지는 않는다.포인터끼리는 뺄 수 있다.
포인터끼리 빼서 나온 값은 포인터와 포인터의 간격을 나타내는 값이기 때문에 포인터에서 포인터를 빼는것은 가능하다.
이때 나오는 값은 메모리의 번지가 아닌 단순한 정수값이다.포인터에 정수를 더하거나 뺄 수 있다.
포인터에 정수를 더하거나 뺄 수 있으며 따라서 증감 연산자(++, --) 도 사용가능하다.
이것은 포인터의 이전 멤버나 다음 멤버를 나타낸다. (대상체의 메모리 ± 대상체의 크기 에 위치하는 메모리 주소)int 형 포인터 ptr이고 메모리 주소가 100일때 ptr - 1 은 ptr 보다 메모리 주소 96을 의미하며
(이전 멤버) ptr + 1 은 메모리 주소 104를 의미한다. (다음 멤버)포인터와 실수의 연산은 할 수 없다.
포인터는 메모리 주소를 가리키는 것이므로 소수점 이하의 값만큼 떨어진 메모리를 가리키는 것은 허용되지 않는다.
포인터에 포인터를 대입할 수 있다.
포인터에 포인터를 대입하는 것은 가능하다. 단 이때 두 포인터의 타입은 동일해야 한다.
포인터에 곱셈과 나눗셈을 사용할 수 없다.
포인터에 곱셈과 나눗셈을 사용하는 것이 불가능한 것은 아니지만, 의미있는 값은 아니므로 사용할 일이 없다.포인터끼리 비교는 가능하다.
해당 포인터의 이전/다음 요소인지 비교하거나, 포인터가 NULL 값인지 확인할 경우 비교할 수 있다.
-------------- 네이버 (세인트)님에 블러그에서 발췌 ------------------------------------