프로그래밍/C언어

C언어 포인터에 대한 이해(3)

콘파냐 2014. 1. 13. 18:40
반응형

포인터 연산

c언어 포인터에 대한 이해 3번째 포스팅 이네요.

 

포인터란 녀석은 참 단순하지만, 완벽히 이해하지 못하면 골머리 썩는 녀석입니다. 그만큼 c언어에 있어서 포인터란 녀석은 자주 쓰이기 때문이죠. 간혹 포인터를 안쓰고 프로그래밍을 한다는 분도 계시지만, 포인터를 안쓰는건 물감없이 수채화를 그리는 것과 다름없다 생각듭니다.

'그럼 이렇게 골머리썩는 포인터를 왜 써야하나요?' 이렇게 질문 하시겠죠?

저는 왜 써야하는지 보단, 포인터가 없다면 많을 것들을 할 수 없기 때문이라 생각됩니다.

물론 포인터말고 좀 더 쉬운 개념의 어떤 문법이 생길지도 모르겠지만, 지금으로서는 포인터로 인해 많은 것들을 할 수 있고, 그런 것들을 경험으로써 익혀 나가게 된다면 포인터는 정말 필요하구나 라고 차차 느껴나가실 겁니다.

 


너무 추상적인 것 같아서 예를 들어보면

 

가장 대표적인 것이 call by value와 call by reference입니다.

값에의한 호출, 참조에의한 호출 입니다.

 

2014/02/11 - [프로그래밍/C언어] - 값에 의한 호출(call by value)과 참조에 의한 호출(call by reference)에 대한 이해 C언어

 

그리고 c++에서 객체를 생성하고 객체를 생성할때 포인터를 사용하지 않을 경우, 덩치 큰 객체를 계속 복사해서 전달해야 합니다.

포인터는 4byte만 전달하면 그만이지만, 객체의 크기는 클래스타입마다 천차만별이란 말이죠.

상상이 가시죠?

 

얼마전에 포스팅한 가상함수가 선언될때 생성되는 vtable 또한 함수포인터배열이구요. 이 vtable을 가르키는 것 또한 vptr 포인터로서 객체멤버변수에 포함됩니다. 모두 두당 4byte입니다.ㅎㅎ

 

하지만 연산실수로 인해서 원하는 값이 아닌 완전 다른값이 나올 수도있고, 생각보다 가독성이 떨어지는 연산이기 때문에 개념을 확실하게 하는 것이 무엇보다 중요합니다.

 

개념을 알면 보면 볼수록 실력이 늘어나고 확실해 지는데 개념이 없으면 보면 볼수록 방해되는 생각들만 머리속에 쌓이게됩니다.

방해되는 생각(완벽하지않은 개념)은 전혀 학습에 도움이 안되고 오히려 마이너스가 때문에, 양질의 문서와 양질의 정보가 정말 중요하다 생각됩니다. 저 또한 부족하지만 그런 양질의 포스팅을 하기 위해 포스팅 하나하나에 정말 신경을 많이 씁니다.

 

그러면 포인터의 연산에 대해서 살펴보도록 하겠습니다.

일반적인 변수의 사칙연산은 사용자가 의도하는 어떤 목적이 있고, 그런 목적들은 컴파일러 차원에서 제한할 필요가 없습니다.

하지만 포인터의 연산은 다릅니다.

포인터가 지니고 있는 값은 오직 대상체의 주소와 타입정보입니다. 이런 제한적이고 중요한 정보를 가진 포인터는 중요한 만큼 제한할 필요도 있습니다.

그러면 이런 포인터의 연산이 어떤 의미를 갖는가를 생각해 봐야합니다.

 

포인터연산

포인터간의 연산은 뺄셈만 가능하다

 

기본적으로 포인터간의 연산은 뺄셈만 가능합니다. 보면 아시겠지만, 포인터의 연산은 가독성이 떨어집니다. 이것은 컴파일러 차원에서 포인터끼리는 덧셈, 곱셈, 나눗셈이 아무런 의미도 없기때문에 실수방지를 위해 에러처리를 해놓은 것입니다.

 

그럼 이젠 포인터와 일반 정수의 연산을 살펴봅시다.

 

위 연산을 주석처리한 후 다음 연산을 추가하여 결과를 보면 곱셉과 나눗셈에 대한 연산을 제외한

덧셈과 뺄셈의 연산을 허용해 줍니다.

위와 다르게 덧셈에 대한 연산을 허용해 주었습니다.

이것은 덧셈연산이 의미가 있다는 뜻이됩니다.

그럼 의미를 알아보겠습니다.

포인터연산

정리(포인터끼리의 연산은 같은 타입의 포인터를 전제로 설명합니다.)

1. 포인터끼리는 -연산만 가능하다.

의미:포인터끼리의 뺄셈은 포인터사이의 거리를 나타낸다.

주의할 점은 연산한 후의 값은 포인터값이 아니다.

 

2. 포인터와 정수의 연산은 +,-이 가능하다.

의미:포인터와 정수의 뺄셈과 덧셈은 배열상에서의 위치, 다시말해 배열요소의 위치를 찾는 방법이다. 문자열도 char배열이기때문에 문자열에서 어떤 특정문자의 위치 또는 특정문자와 특정문자의 거리를 계산하는 데에도 의미가 있을 수 있다.

주의할점은 연산한 후의 값은 포인터값이다.(위 포인터끼리의 연산과는 반대임)

 

간단히 두가지로 정리됩니다. 주의하실건 포인터와 정수가 아닌 수의 연산은 가능하지 않습니다. 왜냐면 의미가 없기때문입니다.

예를 들어 a-4.3f; (X) //포인터와 float형의 뺄셈연산은 의미가 없다. 에러~

 

상식적으로 생각하면 주소값의 합이 의미는 없지만 못 더할 것도 없습니다. 그래서 꼭 더해보고 싶으시다면 unsigned 형으로 캐스팅 한후 더하시면 됩니다. 다시 말하지만 의미는 없습니다.

 

포인터와 비교연산(<,>,>=,<=,!=)

포인터연산에 대해서 컴파일러는 합리적인 판단으로 O,X를 판단하는 걸 알았습니다. 그러면 비교연산에 관해서, 생각해보죠.

 

우선 포인터와 숫자의 비교는 의미가 없겠죠. 물론 직접 주소값을 써넣어 비교하겠다고 하시는 분들이 있다면, 그렇게 프로그래밍을 하는 것은 정말 기운 빠지는 일입니다. 프로그램을 실행할 때마다 변수에 할당되는 주소값도  달라질 뿐 아니라, 직접 주소값을 알 필요가 없이 조작이 가능하니까요.

 

두번째로 포인터와 포인터의 비교입니다. 가능할 듯 싶습니다. 배열내에서 두 포인터간에 상대적 위치는 많은 의미가 있겠죠. 배열값을 순서대로 정렬을 할때도 유용하게 쓰일 겁니다.

그럼 결론을 내려보면 포인터의 비교연산은 포인터끼리만 가능하다

(물론 unsigned 캐스팅을 하면 숫자와도 비교 가능합니다.)

 

연산에대한 이야기가 이렇게 길어질 줄은 몰랐습니다.

정말 간단히 정리만 하려 했는데, 생각보다 중요한 내용이 많았군요.

포인터 연산은 한번에 다 알려고 하기보단 문자열에대한 공부와 c언어 전반적인 공부를 먼저 마친후에 다시금 정리하시는 것이 좋을겁니다.

 

 2013/11/28 - [프로그래밍/C언어] - C언어 포인터에 대한 이해(1)

 

2014/01/12 - [프로그래밍/C언어] - C언어 포인터에 대한 이해(2)

 

배열상에서 포인터연산이 어떻게 쓰이는지에 대해서는 다음에 포스팅을 할까합니다.

반응형