포인터 연산
T형 포인터 ( type )
임의의 타입 T가 있을 때 T형의 포인터 변수를 선언할 수 있다.
int, char , double 등의 기본적인 데이터 타입형의 변수를 선언할 수 있음을 물론이고 구조체, 공용체, 배열에 대해서도 포인터형을 만들 수 있다.
* int , * char , * double
가리키는 대상체(포인터가 가리키는 실체)와 포인터의 타입이 일치해야 한다.
# 이건 기본 상식..
메모리 위치를 가리키는 포인터는 자신이 가리키고 있는 번지에 저장된 값이 어떤 종류인지를 기억하고 있어야 하며 이런 이유로 포인터를 선언할 때 대상체의 타입을 밝혀야 한다.
#증감연산자를 사용해서 현재 위치에서 앞뒤로 이동
번지를 가리키는 포인터도 일종의 변수이므로 실행 중에 다른 번지를 가리키도록 변경할 수 있다.
{ int ar[]={1,2,3,4,5}; int *pi; pi = ar; printf("첫 번째 요소 = %d\n",*pi); pi++; printf("두 번째 요소 = %d\n",*pi); }
|
result)
첫 번째 요소 = 1 , 두 번째 요소 = 2
description)
pi는 ar 배열의 시작 번지 ar[0]의 번지를 가리키고 있는 상황이다.
이 상태에서 *pi를 읽으면 pi 위치에서 4바이트를 읽을 것이며 이 값을 출력하면 첫 번째 요소 1이 출력된다.
그리고 pi++ 연산문으로 pi값을 증가시켜 ar 배열의 다음 요소로 이동했으며 ar[1]의 값이 출력된다.
시작 번지를 1000번지라고 가정할 때 1000번지부터 1003 번지 까지 4바이트를 읽어 ar[0]를 출력하게 된다. ar[1]는 1004번지 ~ 1007번지
* 1000번지에서 증감연산자를 사용했다고 해서 다음 배열이 1001이 되는 것이 아니다!!
그러나 1001번지는 배열에 속해 있기는 하지만 아무런 의미가 없는 값이다. ar[0]도 아니고 두 요소에 걸쳐있는 애매한 번지인 것이다.
이 번지의 값을 읽어서는 ar[1]의 값을 구할 수 없음은 물론이고 이것도 저것도 아닌 이상한 값이 읽혀진다.
T형 포인터 변수 px에 정수 i 를 더하면
px = px+(i*sizeof(T))가 된다.
ex) Type 이 int 일 경우
pi = pi+(i*sizeof(int))
증감연산자를 사용하지않고 실수의 크기만큼 더 할때.
변수의 타입의 사이즈 int일 경우 4바이트의 크기만큼 i의 곱해서 증가한다.
포인터 연산
피연산자 중의 하나가 포인터인 연산이다.
pi++ , pi1-pi2 등 포인터라는 타입이 독특한 타입이기 때문에 연산에 있어서 다른 규칙이 적용된다.
규칙 1 ) 포인터끼리 더할 수 없다.
px = 1000번지 , py = 1500번지
px + py = 2500번지 ??
이 값은 x,y와 논리적으로 아무 상관이없다. 2500번지의 들어있는 값이 x,y와 어떠한 의미도 없다.
규칙2 ) 포인터 끼리 뺄 수 없다.
포인터 끼리 더한 값은 아무런 의미가 없지만 뺸 값은 두 요소간의 상대적인 거리라는 의미가 있다.
포인터끼리의 뺄셈은 원칙적으로 허용되며 실제로 많이 사용된다.
int main() { char ar[]="pointer"; char *pi1, *pi2;
pi1 = &ar[0];
pi2 = &ar[5];
printf("%c와 %c의 거리는 %d\n",*pi1,*pi2,pi2-pi1);
return 0; } |
result)
p와 e 의 거리는 5
pointer
description)
타입이 같은 임의의 두 포인터에 대해 뺄셈이 가능하다. 하지만 일반적으로 두 포인터가 같은 배열내의 다른 요소에 가리키고 있을 때만 실질적인 의미가 있다.
규칙 3 ) 포인터에 정수를 더하거나 뺄 수 있다.
ptr+i , ptr-- 이 가능하다. 앞서 이야기한 것처럼 타입의 크기만큼씩 앞뒤로 이동하면 된다.
ptr1 = ptr2 + 2; / ptr2의 다음다음 요소를 가리킴
ptr1 = ptr2--; / ptr2 의 전 요소를 가리킴
규칙4 ) 포인터끼리 대입 할 수있다.
위에 예제에서 ptr1 = ptr2 를 했듯이 대입이 가능하다.
포인터 타입이 일치해야한다.
규칙 5) 포인터와 실수와의 연산은 허용되지 않는다.
규칙 6) 포인터에 곱셈이나 나눗셈을 할 수 없다.
필요성이 전혀없다.
규칙 7) 포인터끼리 비교는 가능하다.
두 포인터가 같은 번지를 가리키고 있는지를 조사하기 위해 == , !== 상등 비교 연산자 사용할 수 있다.
유효성 검사를 위해 null 값과 비교하는 연산은 자주 이용된다. ( 함수들의 실행 결과를 점검하기 위해서 )
if ( ptr == null )
if ( ptr != null )
포인터 연산 규칙을 한 눈에 알아 볼 수 있는 연산식
* 포인터와 포인터 사이의 중간값을 구하는 식
int ar[]={1,2,3,4,5}; int *p1 , *p2 , *p3; p1 = &ar[0]; p2 = &ar[4]; p3 = p1+(p2-p1)/2; |
description)
p2-p1 : 포인터끼리의 뺼셈 = 정수
(p2-p1)/2 : 정수 나누기 정수 = 정수
p1 + ( p2-p1)/2 : 포인터 더하기 정수 = 포인터
=> 포인터 = 포인터 ( 대입 가능 )
'C,C++' 카테고리의 다른 글
[C,C++] 배열과 포인터 (0) | 2019.02.28 |
---|---|
[C,C++] 이중 포인터 (0) | 2019.02.25 |
[C,C++] 포인터 동적 메모리 할당 (0) | 2019.02.25 |
[C,C++] 포인터의 정의 , 포인터 란? (1) | 2019.02.25 |
[C,C++] 프로그래머의 동기 (0) | 2019.02.25 |