C언어 포인터 개념과 예제, 포인터와 배열

반응형

포인터... 어렵죠.... 여기서부터 C언어 기반 프로그래밍 학습이 조금씩 어려워집니다.
간만에 프로그램언어를 사용하려하니, 포인터와 구조체 부분을 많이 잊어버렸어요...
그래서 복습하려합니다.

1. 포인터 ?
사용하는 이유 : 메모리에 직접 접근하기 위해서용

메모리는 여러가지 영역으로 구성되어있습니다.

1. 코드 영역
-> 코드가 저장되는 공간으로 프로그램을 실행할때, CPU가 직접 코드영역에 저장된 명령어를 가져와 읽게됩니다.
2. 데이터 영역
-> 프로그램이 종료될 때 까지 데이터를 저장하며, 전역변수와 Static이 존재합니다.
3. 스택영역
-> 잠깐 동안의 변수나, 데이터가 저장되는 영역입니다. 지역변수 및 매개변수가 여기에 해당됩니다.
4. 힙영역
-> 동적 할당이라고 들어보셨나요? 나중에 포스트하겠습니다. 사용자가 직접 메모리를 할당하는 방식으로 malloc , calloc 등등이 있으며 free로 해제하게됩니다.
메모리 ?
여러분이 여태까지 선언한 여러 번수들은 메모리의 특정 번지수를 부여받으며, 이 번지수를 '메모리의 주소 값이라합니다. 즉 간단하게 비유하자면 여러분 자신은 변수라 생각하며, 메모리는 아파트라고 생각해보세요. 각자 본인마다 아파트에 몇동 몇호의 주소가 부여될 것입니다. 이게 메모리의 가장 간단한 이해입니다. 

자 그럼 int i; 라고 프로그램을 입력하면 int형 i 변수를 선언했다는 얘기입니다. 이친구는 어디에 저장될까요? 바로 메모리에 저장이됩니다. i를 지역변수로 선언한다면 스택영역에, 일정한 메모리 주소를 할당 받겠죠? 만약 i를 전역변수(global)로 선언하면 당연히 데이터 영역에 저장되겠죠. (이해 안돼면 위에 다시읽어주세요.)

위 코드를 보면 i1=3 ,i2=8을 하였습니다. 당연히 일반적인 변수입니다.
그 다음 코드를 보면 *pi1 , *pi2를 선언하였습니다. *연산자는 포인터가 가리키는 메모리 공간에 접근할때 사용하는 연산자로써 *pi1로 선언되었다는건 pi1를 메모리 공간에 접근 시키겠다라는 이야기입니다. &연산자를 사용하게된다면 &i1를 예로 i1이였으면 그냥 일반 변수였겠죠?
&가 붙음으로써 i1의 값이아닌 i1의 주소값을 반환하라는 이야기입니다.

즉 *pi1은 pi1을 메모리 공간에 접근 시키겠다는 것이며, &i1은 i1의 주소값을 반환 하겠다는 이야기 입니다.

다시 말해 *pi1=&i1를 설명한다면 i1의 (&)주소 값을 *pi1에 저장하여 메모리 공간에 접근 시키겠다는 이야기입니다.

결과창을 보시면 %p를 사용하면 16진수 주소값이 , %u를 사용하면 10진수 주소값이 나옵니다. %d를 사용해도 무방합니다.

그렇게하여 주소값을 출력 할 수 있습니다. 여기까지 잘 이해하셨는지요?

 


 

오늘은 * (역참조 연산자)에 대하여 복습하겠습니다.

포인터 변수를 사용하여 변수의 메모리 저장 주소를 찾았었는데요.
바로 예제로 들어가보겠습니다.

일단 #include<string.h>와 getchar();는 필요없으니 지우셔도됩니다.

자 저는 i1에 22를 저장하였습니다.
그리고 * si1에 i1의 주소값을 저장했습니다.

그리고 출력해본 결과 처음 %d에선 i1의 저장된 값이 출력되었습니다.
두번째 %d는 &si1 즉 si1의 주소값이(10진수) 주소값이 출력되었습니다.
세번째 %p는 &si1 의 16진수 주소값이 출력되었습니다.
자 그럼 마지막 %d에 *si1를 보시면 22가 나왔죠?

감이오시나요? *si1은 여기 메모리에 저장되어있는 변수값을 내놔라 라는 뜻이에요

쉽게말하면 *si1나 i1나 %d로 찍어보면 같은 결과가 출력됩니다.

* (역참조 연산자) 는 해당 메모리 주소에 저장되어있는 값을 지칭하는 연산자입니다.

응용을해볼까요?

간단하죠? 포인터로 선언된 변수끼리도 *로 연산이 가능합니다.

 


C언어 복습 포인터와 배열

 

포인터와 배열은 관계가 있다네요 .. (책에서)

배열자체가 포인터래요. 단, 값을 바꿀수 없는 '상수 형태 포인터' 라는군요.

바로 예제로 들어가보겠습니다.

물론 getchar();는 빼주셔도됩니다.
제가 getchar();를 쓰는이유는 visual studio 2015를 쓰는데 cmd 창이 자꾸 꺼지더라고요.
그래서 getchar();를 사용하여 꺼짐을 방지하였습니다.

따로 포인터 변수를 선언해주지 않아도 &연산으로 바로 주소값을 출력 하는 것이 보이죠?
또한 메모리 주소가 4씩 증가하는 것을 볼 수 있습니다.

왜 4씩 증가하냐고요? int로 배열을 선언하였기때문에 4byte마다 메모리 주소를 할당 받습니다.

아래를 보시면 char로 바꾸니까 메모리 공간이 1byte 마다 할당되었죠? char가 1byte이기 때문에 위와같이 출력됩니다.

또한 위 두 예제 프로그램을 몇번 실행해보면 주소값이 계속 바뀌는 것을 볼 수 있습니다.

포인터 변수와 배열의 공통점은 메모리의 주소값을 저장하고, 나타낸다는것이며
차이점은 포인터 변수는 주소 값의 변경이 가능한데, 배열은 주소값을 변경 할 수 없습니다.

배열과 포인터를 이용하여 몇가지 예제를 실행해볼게요.

이제 배열에 []식으로 출력하지 않아도 , 배열자체에 주소가 있기때문에 *(역참조 연산자)를 이용하여 배열을 출력 할 수 있습니다.

이런식으로 sum을 할 수 도있군요

1차원 배열과 포인터의 관계를 알아봤는데 그렇게 중요하진않아요 그냥 알아두세요 ㅎㅎㅎ

 

댓글

Designed by JB FACTORY